React.js and Flux – Best Practices
What is Flux?
Flux is the application architecture for building client-side web applications. It complements React.js composable view components by utilizing a unidirectional data flow. Flux applications have three major parts: Dispatcher, Stores, and Views.
Component and it’s state
Keep as many of your components as possible – stateless. The common pattern is to create several stateless components that just render data and have a stateful component above theme (root component) in the hierarchy that passes it’s state to it’s children via props.
State should contain data that a component event handlers may change to trigger a UI update.
State should not contain:
- computed data
- react components
- duplicate data from props
In Flux applications all API calls should come from the Action Creators.
There is only one exception to the rule, that only Action Creator call the API: loading initial data. This can be done directly in the view controller.
Loading initial data using asynchronous call:
- fetch data in the componentDidMount lifecycle callback. When the response arrives, store the data in state, triggering a render to update your UI.
- when fetching data asynchronously – use componentWillUnmount to cancel any outstanding requests before component is unmounted.
Stores should remain as independent and decoupled as it possible – a self-contained universe that one can query from a controller view.
The only way into the Store – is through the callback it resters with the Dispatcher. The only way out – it is through getter functions.
Stores also publish an event when their state has been changed, so controller-views can know when to query for the new state using the getters.
Stores should only execute synchronous code. Otherwise they are to hard to understand. This makes your store logic much easier to flow and very easy to test.
If you are using Flux, you should start writing your stores using immutable.js.
Immutable data can not be changed once created…
Immutable.js provides many immutable data structures including: List, Stack, Map, OrderMap, Set, Order Set and Recorder
If we also use immutable.js data structures to hold the components state, we could mix PureRenderMixins into all our components and short circuit re-rendering process.
While waiting for an AJAX API to return, you often want to optimistically update the UI. There is a useful pattern to do it:
- Optimistically update the Store. Do not bypass the store by only saving it in the component state.
- This means you will update the same Store data twice: once based on the user action, and then again based on the received API action or API error action.
- If you need to know if the API action has completed, you can set another variable to track that, along with a getter function that the component can listen for (to display a spinner while some data loads).
Reacting to non-React events
Attach generic DOM-events (e.g. window.resize) to componentDidMount using default window.addEventListener. Then remove event listener in the componentWillUnmount callback. This is a good approach for integrations with other libraries such as jQuery and so on…
React Events System
All events handlers will be passed instance of Synthetic Events – a cross-browser wrapper around the browsers native events.