Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle state transitions in a React / Flux component

Given I have an AJAX based search field that reacts on user input, requests search results from a backend via AJAX, shows the results in a dropdown below the search field, allows navigation through the search results via cursor keys and reacts on esc key presses in an intelligent way.

Since the current Backbone based component is broken in many ways, I'd like to reimplement that search component using React and maybe Flux architecture.

During planning it turned out, that my component has at least a number of 10 different states (maybe even more), it has to react to actions triggered by user inputs, and as well to actions triggered by asynchronous server responses.

Question1: Should I model all state in a store instead of a the parent component? That meant, that every user input changes the stores state, for example the :searchQuery, :searchResults and my parent view component reacts to that state changes?

Question2: Or should I model all state in the parent component itself and omit a store, dispatcher and actions completely?

Question3: Independently from handling state in a store or in the parent component itself, it turned out, that the component itself can have at least 10 different states, and there should only be a certain number of transitions allowed. Usually, I'd pull in a statemachine implementation here, model all :states and allowed :transitions and execute transitions everytime an action is received by the store or a callback method is called in the parent component. What is the correct React way to handle states and transitions between these states in a component?

Question4: Which is the to-go-state-of-the-art Flux implementation for Javascript? I have seen reflux so far, but I'm not sure, that's my poison.

I am open to all kind of suggestions here.

like image 751
GeorgieF Avatar asked Nov 09 '22 17:11

GeorgieF


1 Answers

I am building a similar component in React with flux right now and I have worked with Backbone extensively in the past so hopefully I give you some insight.

My guess is that your Backbone solution had a model local to your search view that built :searchQuery when the field(s) were updated. On the ajax callback you most likely just directly updated the :searchResults.

1-2:

With flux there ends up being a bit more boilerplate code, but in my experience if I don't build a store to start with I always regret it. That being said I would make a SearchStore for the :searchResults and keep the :searchQuery in the state of the parent component.

This way when you are ready to call your search you use a view action SearchViewActions.getSearchResults(:searchQuery) which makes the ajax call and in the callback calls SearchServerActions.receiveSearchResults(:searchQuery, :searchResults) and updates the store. Then your results component can listen for Store changes and call SearchStore.getResults() when it sees the change. This helps modularize the two sub-components, where as option 2 would tightly couple the two components and make it harder for outside component reuse.

3:

I like your solution of the state-machine, that you can just ask if you are allowed to make a transition and return a set of properties to update or a function to execute call setState({...}) based on that information.

4:

Reflux looks great, as it seems to reduce the boilerplate quite a bit. Reflux may or may not perform as well as stock Flux however.

Let me know how it goes, as your strategy may help me improve my structure.

like image 150
Liam Maier Avatar answered Nov 14 '22 22:11

Liam Maier