Нарушение инварианта: Dispatch.dispatch(...): Невозможно отправить в середине отправки

Я использую ALT для своего проекта ReactJS. Я получаю сообщение об ошибке невозможности отправки, если вызов ajax еще не выполнен, и я переключаюсь на другую страницу.

В основном, так настроен мой проект. У меня есть действие, магазин и компонент. Я запрашиваю на сервере на componentDidMount жизненный цикл.

Действие:

  import alt from '../altInstance'

  import request from 'superagent'
  import config from '../config'

  import Session from '../services/Session'

  class EventActions {
    findNear(where) {
      if (!Session.isLoggedIn()) return
      let user = Session.currentUser();

      request
        .get(config.api.baseURL + config.api.eventPath)
        .query(where)
        .set('Authorization', 'Token token=' + user.auth_token)
        .end((err, res) => {
          if (res.body.success) {
            this.dispatch(res.body.data.events)
          }
        });
    }
  }

  export default alt.createActions(EventActions)

хранить

  import alt from '../altInstance'
  import EventActions from '../actions/EventActions'

  class EventStore {
    constructor() {
      this.events = {};
      this.rsvp = {};

      this.bindListeners({
        findNear: EventActions.findNear
      });
    }

    findNear(events) {
      this.events = events
    }

  }

  export default alt.createStore(EventStore, 'EventStore')

Составная часть

  import React from 'react';

  import EventActions from '../../actions/EventActions';
  import EventStore from '../../stores/EventStore';
  import EventTable from './tables/EventTable'

  export default class EventsPage extends React.Component {
    constructor(props) {
      super(props);

      this.state = {
        loading: true,
        events: [],
        page: 1,
        per: 50
      }
    }

    componentDidMount() {
      EventStore.listen(this._onChange.bind(this));
      EventActions.findNear({page: this.state.page, per: this.state.per});
    }

    componentWillUnmount() {
      EventStore.unlisten(this._onChange);
    }

    _onChange(state) {
      if (state.events) {
        this.state.loading = false;
        this.setState(state);
      }
    }

    render() {
      if (this.state.loading) {
        return <div className="progress">
          <div className="indeterminate"></div>
        </div>
      } else {
        return <div className="row">
            <div className="col m12">
              <h3 className="section-title">Events</h3>
              <UserEventTable events={this.state.events}/>
            </div>      
        </div>
      }
    }
  }

3 ответа

componentDidMount() {
      EventStore.listen(this._onChange.bind(this));
      EventActions.findNear({page: this.state.page, per: this.state.per});
    }

Это будет моя догадка. Вы связываете onChange, который будет вызывать setState в _onChange, а также будет запущено действие из findNear (из-за отправки). Так что может быть момент, когда оба обновляются одновременно.

Прежде всего, findNear, по моему мнению, должен быть первым в componentDidMount.

А также попробуйте разделить его на 2 разных представления (тупой и логический, где первый будет отображать только данные, а другой, например, будет выполнять выборку). Также хорошей идеей является также использование AltContainer, чтобы фактически избежать действия _onChange, которое довольно бесполезно из-за того, что AltContainer имеет подобные вещи "внутри".

constructor() {
  this.events = {};
  this.rsvp = {};
  this.bindListeners({
    findNear: EventActions.findNear
  });
}

findNear(events) {
  this.events = events
}

Также я бы рефакторинг этого в

constructor() {
  this.events = {};
  this.rsvp = {};
}

onFindNear(events) {
  this.events = events
}

У Alt есть довольно приятные вещи, такие как автоопределители, которые будут искать имя действия + on, поэтому если у вас есть действие с именем findNear, оно будет искать onFindNear.

Я не могу понять, почему вы получите эту ошибку, потому что код, который вы предоставили, показывает только одно действие.

Однако я предполагаю, что ваш компонент был смонтирован в результате какого-либо другого действия в вашей системе. Если это так, то ошибка будет вызвана действием, инициируемым в componentDidMount,

Может быть, попробуйте использовать Alt's action.defer:

componentDidMount() {
    EventStore.listen(this._onChange.bind(this));
    EventActions.findNear.defer({page: this.state.page, per: this.state.per});
}

Я полагаю, это потому, что вы вызываете действие, и отправка этого действия происходит только после завершения запроса.

Я бы предложил разделить действие findNear на три действия: findNear, findNearSuccess и findNearFail.

Когда компонент вызывает findNear, он должен отправлять немедленно, даже до отправки запроса, чтобы соответствующие компоненты обновлялись в соответствии с выполняемым запросом (например, отображать знак загрузки, если хотите)

и внутри того же действия он должен вызвать другое действие findNearSuccess.

Статья " Извлечение данных" должна быть особенно полезной.

Другие вопросы по тегам