In my earlier post, I compared the performance and memory profiles of a benchmark application written in AngularJS, React/Redux and React/Mobx. It’s quite obvious from the metrics that React with Redux or Mobx gives significant performance gains compared to AngularJS. In this post, I will go over the core concepts, benefits and gotchas with both the libraries.
All the below code snippets are from the ticker dashboard application from my earlier post.
Redux flow diagram
http://redux.js.org/docs/introduction/ThreePrinciples.html
The state of your whole application is stored in an object tree within a single store.
Here is the UI state tree for the stock ticker dashboard application.
UI State tree
The only way to change the state is to emit an action, an object describing what happened.
Action creator is a function returning the action object. In the below example, each Action is represented with a ‘type’ and ‘payload’.
Action Creators
To specify how the state tree is transformed by actions, you write pure reducers.
Reducers are pure functions that modify the state in immutable way (returns new objects instead of mutating the object). Reducers shouldn’t cause side effects like making external api calls, triggering route changes.
Reducers
If we design the action interfaces to have a common property (‘type’ in this example), we can leverage TypeScript’s discriminated unions to get type checking as well as the intellisense support in each case statement.
Usage with React · Redux_Technically you could write the container components by hand using store.subscribe() . We don't advise you to do this…_redux.js.org
React-Redux library provides a Higher order React component which automatically listens for store.subscribe(listener)
events. When an action is dispatched to the store, Redux will notify the state changed event to all subscribers. All “React-Redux” connected components are subscribers to the Redux store and every connected component’s mapStateToProps method is executed with every state change. This method helps you to slice the UI state tree and pick the data needed for the specific component tree.
Pure components are normal React components. They read data from props to render and execute the callbacks sent via props. They are not aware of Redux or UI state tree.
Here is how the component hierarchy would look:
Connected Components And Pure Components
Here is an example of the connected component. TickerTile component renders stock ticker details (ticker, company name, price, sma, volume etc) and depends on the tickerData as a prop. The parent component just sends the tickerId (e.g. MSFT) as prop (termed as ownprops). The Higher Order connect component takes mapStateToProps mapper function which takes the tickerId and returns tickerData from UI state’s tickerHash and tickerId.
TickerTile
React-Redux Connected Component
Here is an example of the pure component:
Pure Component
Designing UI State tree
https://twitter.com/dan_abramov/status/727278011591045122
Helpful links:
Connected Components (containers) mapStateToProps method of all connected components will be executed with every state changed event of the Redux store. Optimizing this method is one of the critical steps to get optimal performance in complex applications. If you need to execute expensive operations like deriving computed data from the normalized state tree, use Redux reselect library. It memoizes the result and skips recalculating unless input references change (there is a gotcha if you’re trying to reuse the selectors in multiple components).
If there are minimal connected components, props need to be propagated several levels down of the component hierarchy which is clearly not ideal in the large applications. Redux used to recommend connecting few components to the Redux store. Now, the recommendation is to use as many as you need.
In the stock ticker dashboard application from my previous post, In the updates test scenario, with 1500 tickerTile (connected) components in the view, Redux refreshed the price/volume changes within 6ms.
These two PRs (authored by Dan Abramov, creator of Redux) achieved substantial performance gains by connecting several components to Redux store and by optimizing mapStateToProps.
Helpful Link(s):
**Batch dispatch calls**Anytime Redux’s dispatch method is called with an action, Redux executes all reducers, updates the state and notifies all the subscribers synchronously. React-Redux will then trigger mapDispathToProps on all the connected components.
If you’re updating different sections of the state tree through multiple actions at the same time, try to batch them to trigger only one notification.
Helpful Links:https://github.com/markerikson/redux-ecosystem-links/blob/master/store.md#store-change-subscriptionshttps://github.com/reactjs/redux/issues/2108http://blog.isquaredsoftware.com/2017/01/idiomatic-redux-thoughts-on-thunks-sagas-abstraction-and-reusability/#multiple-dispatching
**Redux Libraries**Redux is a tiny state management library (with minimal API) which acts as a building block for the higher level constructs. You need to bring in a lot of libraries to put together any real world application. It might be overwhelming at first (esp. for folks coming from AngularJS) but most of these libraries are small and come with good documentation.
https://github.com/reactjs/reselecthttps://github.com/paularmstrong/normalizrhttps://github.com/omnidan/redux-ignorehttps://github.com/gaearon/redux-thunkhttps://github.com/evgenyrodionov/redux-loggerhttps://github.com/tshelburne/redux-batched-actionshttps://github.com/tappleby/redux-batched-subscribe
**Functional Programming**Redux uses several functional programming patterns (currying, higher order functions, composition etc.). The patterns and code might look strange for folks coming from object oriented design background. But Redux comes with a great documentation and there are a ton of great articles/videos out there to gain familiarity with the patterns.
From, https://mobx.js.org/
Both React and MobX provide very optimal and unique solutions to common problems in application development. React provides mechanisms to optimally render UI by using a virtual DOM that reduces the number of costly DOM mutations. MobX provides mechanisms to optimally synchronize application state with your React components by using a reactive virtual dependency state graph that is only updated when strictly needed and is never stale.
Mobx flow diagram (source: https://mobx.js.org/)
https://mobx.js.org/intro/concepts.html
MobX adds observable capabilities to existing data structures like objects, arrays and class instances.
Observable State
Derivations
Anything that can be derived from the state without any further interaction is a derivation (user interface, computed values).
User interface derivation
OR
/* a function that observes the state */autorun(function() { console.log("Total Tickers", tickerDataModel.getAllTickers().length );});
Actions are functions that modify state.
All Derivations are updated automatically and atomically when the state changes. As a result, it is never possible to observe intermediate values.
All Derivations are updated synchronously by default. This means that, for example, actions can safely inspect a computed value directly after altering the state.
Actions in Mobx
Helpful links:https://medium.com/@mweststrate/becoming-fully-reactive-an-in-depth-explanation-of-mobservable-55995262a254https://mobx.js.org/best/pitfalls.html
Thanks for reading.
P.S. Thanks to Shyam Arjarapu for reviewing this article.