Understanding the working principle of Redux?#
1. What is it#
React
is used to build user interfaces and helps us with the process of rendering the DOM
.
In an entire application, there can be many components, and each component manages its own state
, including defining its own state
, communication between components through props
, and using Context
to share data.
If each component stores its own related state, theoretically it will not affect the operation of the application. However, during development and maintenance, we will spend a lot of effort querying the process of state changes.
In this case, if all states are managed centrally, when an update to the state is needed, it only needs to be handled by this centralized management, without worrying about how the state is distributed to each component.
redux
is a container that implements the above centralized management and follows three basic principles:
- Single source of truth
- State is read-only
- Use pure functions to perform modifications
It is important to note that redux
is not only applied in react
, but also used with other UI libraries, such as Vue
.
2. Working Principle#
redux
requires us to put all data in the store
, which is a common storage space.
When a component changes the data in the store
, other components can perceive the changes in the store
and then retrieve the data, indirectly achieving the functionality of data transmission.
The workflow is shown in the following diagram:
Based on the diagram, we can imagine that React Components
are users borrowing books, Action Creator
is what is said when borrowing books (what book to borrow), Store
is the librarian, Reducer
is the record book (what book to borrow, what book to return, where it is, need to check), and state
is the book information.
The entire process is that the user borrowing books needs to exist first, then needs to borrow books, and needs a sentence to describe what book to borrow. After hearing this, the librarian needs to check the record book to understand the location of the book. Finally, the librarian will give the book to the borrower.
In terms of code, React Components
need to retrieve some data, and then it informs the Store
to retrieve the data. This is the Action Creator
. The Store
receives it and checks with the Reducer
. The Reducer
will tell the Store
what data should be given to this component.
3. How to use#
Create a common data area for the store
.
import { createStore } from 'redux' // Import a third-party method
const store = createStore() // Create a common storage area for data (librarian)
You also need to create a record book to assist in managing data, which is the reducer
. It is essentially a function that takes two parameters, state
and action
, and returns state
.
// Set default values
const initialState = {
counter: 0
}
const reducer = (state = initialState, action) => {
}
Then you can pass the record book to the store
to establish a connection between them. Like this:
const store = createStore(reducer)
If you want to retrieve the data in the store
, you can use store.getState()
to get the current state
.
console.log(store.getState());
Next, let's see how to change the data in the store
. It is done by dispatching an action using dispatch
. Usually, the action will have a type
property, and it can also carry other data.
store.dispatch({
type: "INCREMENT"
})
store.dispath({
type: "DECREMENT"
})
store.dispatch({
type: "ADD_NUMBER",
number: 5
})
Now let's look at how to modify the processing logic in the reducer
:
const reducer = (state = initialState, action) => {
switch (action.type) {
case "INCREMENT":
return {...state, counter: state.counter + 1};
case "DECREMENT":
return {...state, counter: state.counter - 1};
case "ADD_NUMBER":
return {...state, counter: state.counter + action.number}
default:
return state;
}
}
Note that the reducer
is a pure function and does not need to directly modify the state
.
After dispatching the action, you can listen to the changes in the store
through store.subscribe
, like this:
store.subscribe(() => {
console.log(store.getState());
})
In a React
project, it is used in conjunction with react-redux
.
The complete code is as follows:
const redux = require('redux');
const initialState = {
counter: 0
}
// Create a reducer
const reducer = (state = initialState, action) => {
switch (action.type) {
case "INCREMENT":
return {...state, counter: state.counter + 1};
case "DECREMENT":
return {...state, counter: state.counter - 1};
case "ADD_NUMBER":
return {...state, counter: state.counter + action.number}
default:
return state;
}
}
// Create a store based on the reducer
const store = redux.createStore(reducer);
store.subscribe(() => {
console.log(store.getState());
})
// Modify the state in the store
store.dispatch({
type: "INCREMENT"
})
// console.log(store.getState());
store.dispatch({
type: "DECREMENT"
})
// console.log(store.getState());
store.dispatch({
type: "ADD_NUMBER",
number: 5
})
// console.log(store.getState());
Summary#
createStore
helps create a store.store.dispatch
helps dispatch an action, and the action will be passed to the store.store.getState
can be used to retrieve all the data in the store.store.subscribe
method subscribes to changes in the store. Whenever the store changes, the callback function received bystore.subscribe
will be executed.