โบ Intro to Redux
Last updated
Last updated
Redux is a state management system for cross-component
or app-wide state
.
We may have deeply nested JSX code (as seen in the code below) with a lot of context Providers
, or we may have one huge context provider, but which is not maintainable (as in the code below that). This issue is usually seen in large, enterprise level applications, generally.
React Context is not good for high frequency updates, but is better for low-latency updates in the state.
This is from Sebastian Markbรฅge, who is a part of the Facebook React Team:
My personal summary is that new context is ready to be used for low frequency unlikely updates (like locale/theme). It's also good to use it in the same way as old context was used. I.e. for static values and then propagate updates through subscriptions. It's not ready to be used as a replacement for all Flux-like state propagation.
Redux, on the other hand, does not have these disadvantages.
Redux maintains a Central Data Store
for the state
that we want to manage across components or the whole app.
The components that are dependent on the states stored in the central data store, subscribe
to the states in this central data store, and re-evaluate and re-execute when the state changes in the central data store.
NOTE: The components do no directly mutate/manipulate the state in the central data store! Instead, we have a Reducer Function
which mutates the state in the central data store. This reducer function is not the useReducer()
hook, but more of a general concept of reducer functions [which transform an input, and spit out an output after performing that transformation, based on the action received, which is a similar concept used in the useReducer()
hook].
The way we connect the reducer function to the component is via the Actions
. The component dispatch
or trigger
an Action
. The Action
is a simple JavaScript object, that describes the kind of action the reducer function should perform. Redux then forwards
the Actions
to the reducer function
, where the reducer function
reads the description of the desired operation from the Actions
, and then performs the necessary changes (transforms the data
) in the state to be updated in the Central Data (state) Store
.
Once the state in the data store is updated by the reducer function, the subscribed
components are notified about the change in state so that they can update their UI.
We run the JavaScript file using nodeJS
. To get this setup, follow the below steps:
NodeJS
needs to be installed beforehand.
Create a new empty folder, and add a file called redux-demo.js
Open this folder in the terminal and run the following command to install the redux
external library:
redux
redux
with nodeJS
syntaxCentral Store
The central store is the place where we store our state data, and which will be manipulated via the reducer function
. We create the store using the createStore()
function available in Redux.
Reducer
functionThe reducer function should be a pure function
, meaning, the input it gets, should lead to same output, and should not have any side-effects within it. The reducer function has two inputs:
Old State
Dispatched Action
The output:
A new State Object
We need to give the default value to state, since when the store is created with the pointer to the reducer function, the reducer function is executed for the first time the code runs, and will initialize the default value on the first run. If we do not do this, it will throw an error saying that the state is undefined
. This default value is used only for the first time when the reducer function is created. Thereafter, the default value is then ignored and the current state value is used going forward.
After the reducer function is created and connected to the store, to notify that this is the reducer function that will update the state in the store, we need to create a subscription, so as to update the state when the component sends an action
to the reducer function to update the state.
Subscriber
functionThe subscriber usually subscribes to state changes to the store. It sends actions
to the reducer fn
to update the state in the store.
The subscription function in this demo code gets the latest snapshot of the state in the central store by calling the getState()
function on the store that we created earlier (available on the store in Redux).
Now we need Redux to be aware of the subscriber
function so that it knows that the subscriber function should be executed when the state changes in the store. This is done using the subscribe()
function that is available in Redux.
action
Action is a JavaScript object with property type
, which is usually a string, but can be any data type.
Besides calling getState
and subscribe
methods on the Redux store
, we can also call dispatch()
which dispatches the action from the subscriber, to the reducer.
nodeJS
:The counter state is 2
because, initially when the reducer is created and executed, i.e, when the store is created, the default counter
value is set to 0
(from the parameters), and when the counterReducer
is executed for the first time, the counter value increments to 1
. Then, when we dispatch the action increment
to the reducer, the counter gets incremented by 1 again. This causes the state to change from 1
to 2
. Due to this change, the subscriber counterSubscriber
gets executed, which logs the latestState
which is actually store.getState()
, and hence we see the result {counter: 2}
.
To avoid counter increment at initialization, we have the action
type
being sent from the dispatch()
function call, which we can check in the reducer function, and based on the action type, we can change the state.
With the above code changes, we can see when we run the redux-demo.js
file again, the output is:
The counter is initially set to 0 by default and is only updated IF the action is increment
, which is dispatched to the reducer.
The same can be followed to decrement the counter value at decrement
action, which again needs to be dispatched to the reducer via the dispatch()
call on the store
object.
Now if we have multiple increment
and decrement
actions dispatched to the reducer, we will have an output like so:
Hence, using redux
library is not limited to React, but it can be used with any project in JavaScript, and also has been implemented in various other programming languages.