On React Flux, where should I fill in the initial state of my stores?

I am learning Flux and I think I understood the workflow:

View -> Action -> Dispatcher -> Store -> View 

However, I did not quite understand where I should fill in the initial state of my stores.

For example, let's say I'm editing Contact. Therefore, I would suggest that I have a ContactsStore . This is what I think will happen when I get the URL /contacts/edit/23 :

  • Somehow my ContactsStore filled with the contact that I am editing, in this case I am contacting 23. The data will come from the server.
  • A notification from ContactsStore will be received in the EditContact view, so it will be displayed in its original state.
  • When I save the contact, the view will trigger the SaveContact action, and the stream will continue.

Step (1) is not clear to me. Where is the initial ContactsStore expected? Where can I call the server? Is it in the store?

Thanks.

+5
source share
4 answers

You need to have access to the action and repository in your EditContact component. In the componentDidMount handler, you can run an action that executes an api request. By success, it passes the contact to the dispatcher / store . As soon as the store receives contact , it fires an event that EditContact . In the corresponding handler, the component sets a new state with a new contact. I am sure there are other ways to do this, but how will I do it.

+5
source

Like me, and I think many others, I call an action from the view to load the contact. Let me call it LOAD_CONTACT . This will be an asynchronous action. Some people directly bind the API call in the store, but I think the more frequent activity was async in action creators. So, let's say you have the creator of the loadContactAction() action. Then it will first send the LOAD_CONTACT action (in case some store might be interested in it, to display the message “loading” or something else), then select from the API. In the ajax request callback, you call another action creator, for example. loadContactSuccessAction() (or "failed", of course). Then your ContactsStore store registers and responds to LOAD_CONTACT_SUCCESSFUL .

 var loadContactAction = function(...) { // maybe do some work dispatch(...); // dispatch your LOAD_CONTACT action makeRequest(...).then(function(contact) { loadContactSuccessAction(contact); // create "success" action }, function(err) { loadContactFailedAction(err); // probably handle this somewhere }); } var ContactsStore = { init(...) { // register in dispatcher here }, onLoadContactSuccess(contact) { this.contacts[contact.id] = contact; // or store your contact some other way this.emitChange(); // trigger a store update change event with whatever event dispatcher you use } } var EditContact = React.createClass({ componentDidMount: function() { ContactsStore.listen(this.onStoreChange); loadContactAction(); // pass in ID or however you want to load it }, onStoreChange: function() { // fetch your contact here }, render: function() { ... } }); 
+3
source

I agree with Florian Gl’s answer, although I would recommend reading the article below about higher-order components, you should leave the logic from your component and use a higher-order component that passed data as a props, avoiding using the state as much as possible, it will add only extra complexity

in your top-level component (container): componentWillMount handler, you can launch an action that executes an api request when this state is successfully stored in the store, and as soon as the store receives a contact, it fires an event at which the EditContact Container component subscribes → which is passed editContact component

The state should live in your store :)

https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750

+1
source

When you create the initial state of your application, you must run an action to retrieve the data for "contact 23". This action causes an asynchronous call, which results in an event that populates the storage that the component uses to get its state.

However, do you want to put the logic that triggers the action in this component? Not necessary. Do you use any routing libraries? If so, they are probably the best place to trigger action.

For example, using fluxible-router , its routing configuration allows you to specify that each route (for example, /contacts/23 ) should work.

This allows you to separate the data from how to get it from the display. You can use the same component and get its data from AJAX in one case, from local storage in another case, etc. You can also optimize data sampling, for example. by combining multiple calls without changing any components.

0
source

All Articles