Latest news about Bitcoin and all cryptocurrencies. Your daily crypto news habit.
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
Core Concepts
http://redux.js.org/docs/introduction/ThreePrinciples.html
Single source of truth (UI State Tree)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 treeActionsThe 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 CreatorsReducersTo 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.
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.
Connected and Pure (Presentational) UI Components
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.
TickerTileReact-Redux Connected Component
Here is an example of the pure component:
Pros
- Everything with Redux is very explicit without any magic.
- Reactâs deterministic state changes and view renders are great for testability and easy to debug any issues.
- Redux patterns force developers to think hard on the schema of the UI state tree.
- Patterns will be consistent across the codebase (at the cost of verboseness).
- UI would simply become the representation of the state tree. Changes to the State tree can be easily traced/monitored as the actions play out.
- Great Documentation and excellent community support.
Few things to watch out for
Designing UI State tree
- Make sure your UI state tree is normalized and try to keep it as flat as possible (instead of deeply nested structures). At times, deciding whether a property should go into the UI state or not can be confusing. Using local component state is fine as long as other parts of the application do not care about it.
https://twitter.com/dan_abramov/status/727278011591045122
Helpful links:
- http://redux.js.org/docs/faq/OrganizingState.html#do-i-have-to-put-all-my-state-into-redux-should-i-ever-use-reacts-setstate
- https://spin.atomicobject.com/2017/06/07/react-state-vs-redux-state/
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.
- Redux vs mobxâââhttps://github.com/mweststrate/redux-todomvc/pull/1
- PixelPaintâââhttps://github.com/dtinth/pixelpaint/pull/1
Helpful Link(s):
Batch dispatch callsAnytime 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 LibrariesRedux 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 ProgrammingRedux 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.
Mobx
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/)
Core Concepts
https://mobx.js.org/intro/concepts.html
Observable StateMobX 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
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
Pros
- A lot less mental overhead (no need to normalize state, no single ui tree, no reducers, no optimizing mapStateToProps, no connected components).
- Developer velocity and productivity. You can very quickly put together decent sized applications with Mobx and the code also scales well within the large teams.
- Porting services/view models from AngularJS application would be straight forward.
- Mobx with React is blazingly fast in scenarios cut out for it. During the updates test scenario (from my earlier post), Mobx refreshed price/volume changes with-in 2ms (with 1500 tickers on the page).
Few things to watch out for
- Mobx automatically runs all derivations (updating views, updating computed properties) whenever the state changes. It internally manages the dependency state graph. Its implicit nature of updates feels like magic. This may become problematic in large applications where you might prefer more control. (just my opinion, I may be wrong).
- Observable arrays inherit from Object instead of Array, so the external libraries (like lodash) wonât be able to detect Observable arrays correctly. You need to convert to regular Array by calling observable.toJS() or observable.slice().
- Mobx had higher memory footprint than Redux in some of my test scenarios. This may not be a big deal for most of the applications but please test out your specific scenarios.
- For promises, every callback handler needs to wrapped with @action and derivations will be triggered for every callback handler.
- Mobx synchronously triggers derivations whenever an observable property is changed, this can cause performance bottlenecks. Enforcing strict mode right from the beginning helps with this issue.
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.
Introduction to Redux and Mobx was originally published in Hacker Noon on Medium, where people are continuing the conversation by highlighting and responding to this story.
Disclaimer
The views and opinions expressed in this article are solely those of the authors and do not reflect the views of Bitcoin Insider. Every investment and trading move involves risk - this is especially true for cryptocurrencies given their volatility. We strongly advise our readers to conduct their own research when making a decision.