State management with Redux and friends

React provides basic state management within React components, but sometimes it is not sufficient, especially when your application needs to share state between multiple components. State management solutions like Flux, Redux, and MobX and quite popular in the React world and JHipster uses Redux as the state management layer.

When should you use the React component state?
  • If the variable can always be calculated using a prop: Don't use component state, calculate the variable during rendering
  • If the variable is not used in rendering but to hold data: Don't use component state, use private class fields
  • If the variable is obtained from an API and is required by more than one component: Don't use component state, use Redux global state and pass the variable as a prop

Redux (https://redux.js.org/) is a predictable state management solution for JavaScript, evolved from the Flux concept (https://facebook.github.io/flux/). Redux provides a global immutable store which can only be updated by emitting or dispatching actions. An action is an object which describes what changed, and it uses a pure reducer function to transform the state. A reducer is a pure function which takes in the current state and action and returns a new state.

React Redux is a binding for Redux that provides a higher order component called connect for React, which is used to connect React components to the Redux store. Let's take a look at src/main/webapp/app/modules/home/home.tsx, for example:

export class Home extends React.Component<IHomeProp, IHomeState> {
...
}

const mapStateToProps = storeState => ({
account: storeState.authentication.account,
isAuthenticated: storeState.authentication.isAuthenticated
});
const mapDispatchToProps = { getSession };

export default connect(mapStateToProps, mapDispatchToProps)(Home);

The mapStateToProps function is used to map properties from the global Redux store to the components props. The mapDispatchToProps function is used to wrap the given functions with the Redux dispatch call.

Redux Promise Middleware (https://github.com/pburtchaell/redux-promise-middleware) is used to handle asynchronous action payloads. It accepts a Promise and dispatches pending, fulfilled, and rejected actions based on the Promise state. It is useful when Redux actions are making HTTP requests or performing async operations.

Redux Thunk (https://github.com/gaearon/redux-thunk) is another middleware used to chain actions. It is useful when an action has to call another action based on certain conditions or in general to handle side effects.