Evitando cadeias de eventos com dependências de dados assíncronas

O distribuidor do Facebook Fluxproíbe explicitamente o ActionCreators de enviar outros ActionCreators. Essa restrição é provavelmente uma boa idéia, pois impede que seu aplicativo crie cadeias de eventos.

No entanto, isso se torna um problema, pois você tem armazenamentos contendo dados de ActionCreators assíncronos que dependem um do outro. E seCategoryProductsStore depende deCategoryStore parece não haver uma maneira de evitar cadeias de eventos sem recorrer ao adiamento da ação de acompanhamento.

Cenário 1: Uma loja que contém uma lista de produtos em uma categoria precisa saber de qual ID de categoria ela deve buscar produtos.

var CategoryProductActions = {
  get: function(categoryId) {
    Dispatcher.handleViewAction({
      type: ActionTypes.LOAD_CATEGORY_PRODUCTS,
      categoryId: categoryId
    })

    ProductAPIUtils
      .getByCategoryId(categoryId)
      .then(CategoryProductActions.getComplete)
  },

  getComplete: function(products) {
    Dispatcher.handleServerAction({
      type: ActionTypes.LOAD_CATEGORY_PRODUCTS_COMPLETE,
      products: products
    })
  }
}

CategoryStore.dispatchToken = Dispatcher.register(function(payload) {
  var action = payload.action

  switch (action.type) {
    case ActionTypes.LOAD_CATEGORIES_COMPLETE:
      var category = action.categories[0]

      // Attempt to asynchronously fetch products in the given category, this causes an invariant to be thrown.
      CategoryProductActions.get(category.id)

      ...

Cenário 2: Outro cenário é quando um componente filho é montado como resultado de uma alteração da loja e suacomponentWillMount/componentWillReceiveProps tenta buscar dados por meio de um ActionCreator assíncrono:

var Categories = React.createClass({
  componentWillMount() {
    CategoryStore.addChangeListener(this.onStoreChange)
  },

  onStoreChange: function() {
    this.setState({
      category: CategoryStore.getCurrent()
    })
  },

  render: function() {
    var category = this.state.category

    if (category) {
      var products = <CategoryProducts categoryId={category.id} />
    }

    return (
      <div>
        {products}
      </div>
    )
  }
})

var CategoryProducts = React.createClass({
  componentWillMount: function() {
    if (!CategoryProductStore.contains(this.props.categoryId)) {
      // Attempt to asynchronously fetch products in the given category, this causes an invariant to be thrown.
      CategoryProductActions.get(this.props.categoryId)
    }
  }
})

Existem maneiras de evitar isso sem recorrer ao adiamento?

questionAnswers(2)

yourAnswerToTheQuestion