React, Redux and Redux-Saga
A short note about the evolution from React to the need of Redux and some supporting tool chain for it.
How React works (at a very high level)
- A React app has a bunch of components
- Each of them renders some DOM elements
- In addition, they can hold some state, e.g. a counter component can hold the current number
- Some of the elements can handle some events that will update the state
- React subscribe to these state changes and will render the component accordingly
Everything is great until you app have many components, user actions might trigger changes in multiple components' states, if one component want to change something about its peer component usually it needs to inform the state of their parent components and things (the flow of data can) get hard to track quickly.
Alternatively, you can a single gigantic state at the root component that holds the state of every component and passes it down to all of its recursive children components. This is basically the approach Redux took.
- There is a single store that holds the state of everything (it's a large object, you can of course organize its field to be objects recursively to best represent the logic in your data)
- Then you write a bunch of reducers that (currentState, action) => newState
- Reducers is the center of redux
- The store is accessible by all components (you can use a context provider for that)
- Therefore in each component, you can read the current state (part of it) that's relevant for this component), and they can dispatch actions to change the state.
store.subscribe(render)can connect UI rerender when action is dispatched (https://egghead.io/lessons/react-redux-store-methods-getstate-dispatch-and-subscribe); this is done at the component level (container components that hooks store to presentational components); the common boilerplate are abstracted away by connect() (https://react-redux.js.org/api/connect)
- More recently react Redux provide a few useful hooks to reduce the boilerplate
- We can read data from the store with
useSelector, and dispatch actions using
useSelectorspecifies a selector function that maps state to prop, it also subscribes such function to changes to the state, and run your selector when an action id dispatched
- Some minor/useful abstractions: action creators are functions that given some params produce the action object
These changes follow the Flux architecture and make React purely responsible for the view (and user interactions) and leave state management to Redux completely which enforces unidirectional data flow
Thunk is a way to help async actions
But Redux Saga is better than that somehow.
- We saw that using Effects like
put, combined with high-level APIs like
takeEveryallows us to achieve the same things as
redux-thunk, but with the added benefit of easy testability.
This is pretty amazing, Dan (the author of Redux) explains Redux starting from scratch
A quick recap of React if you need it