Original link: https://www.iyouhun.com/post-228.html
Introduction to React-Redux
Why use the React-Redux bindings library?
React and Redux are two separate libraries with separate responsibilities. Therefore, in order to implement state management with Redux in React, a mechanism is needed to link these two separate libraries together. At this time, the binding library React-Redux is used.
- Function: Access Redux for React to implement state management using Redux in React .
- The react-redux library is the React binding library officially provided by Redux.
basic use
The use of react-redux is divided into two major steps: 1. Global configuration (only need to be configured once) 2. Component access (to obtain status or modify status)
First look at the global configuration:
Steps :
- Install react-redux:
yarn add react-redux
- Import the Provider component from react-redux
- Import the created redux repository
- Use Provider to wrap the entire application
- Set the imported store as the value of the Provider’s store property
Core code :
In src/index.js:
// 导入Provider 组件import { Provider } from 'react-redux' // 导入创建好的store import store from './store' const root = ReactDOM.createRoot(document.querySelector('#root')) root.render( <Provider store={store}> <App /> </Provider> )
get status useSelector
-
useSelector
: Get state data provided by Redux - Parameters: selector function, which is used to filter out the required state data from the Redux state and return it
- Return value: filtered status
import { useSelector } from 'react-redux' // Redux 中的状态是数值,所以,可以直接返回state 本身const count = useSelector(state => state) // 比如,Redux 中的状态是个对象,就可以: const list = useSelector(state => state.list)
example:
import { useSelector } from 'react-redux' const App = () => { const count = useSelector(state => state) return ( <div> <h1>计数器:{count}</h1> <button>数值增加</button> <button>数值减少</button> </div> ) }
Dispatch action useDispatch
-
useDispatch
: Get the dispatch function, distribute the action, and modify the state data in redux -
grammar:
import { useDispatch } from 'react-redux' // 调用useDispatch hook,拿到dispatch 函数const dispatch = useDispatch() // 调用dispatch 传入action,来分发动作dispatch( action )
example:
import { useDispatch } from 'react-redux' const App = () => { const dispatch = useDispatch() return ( <div> <h1>计数器:{count}</h1> {/* 调用dispatch 分发action */} <button onClick={() => dispatch(increment(2))}>数值增加</button> <button onClick={() => dispatch(decrement(5))}>数值减少</button> </div> ) }
Understanding Redux data flow
- Any component can directly access Redux, that is, you can directly: 1 Modify the Redux state 2 Receive the Redux state
- And, as long as the state in Redux changes, all components that receive the state will be notified, that is, the latest Redux state can be obtained
- In this way, no matter how far apart the two components are, they can communicate directly
code structure
When using Redux for project development, action/reducer/store will not be placed in the same file, but will be split
Redux code can be organized according to the following structure:
/store --- 在src 目录中创建,用于存放Redux 相关的代码/actions --- 存放所有的action /reducers --- 存放所有的reducer index.js --- redux 的入口文件,用来创建store
Use of ActionType
-
Action Type refers to: the value of the type attribute in the action object
-
Action types are used many times in Redux projects, such as action objects, reducer functions, dispatch(action), etc.
-
Goal: Centralize the processing of action types and maintain the consistency of action types in the project
-
The value of action type is in the form of:
'domain/action'(功能/动作)形式
for classification processing, for example,- Counter:
'counter/increment'
represents the increment action in the Counter function - Login:
'login/getCode'
indicates the action of logging in to get the verification code - Profile:
'profile/get'
means get profile
- Counter:
Steps :
- Create an
actionTypes
directory or aconstants
directory in the store directory for centralized processing - Create constants to store action types and export
- Replace the place where the action type is used in the project with these constants, so as to maintain the consistency of the action type in the project
// actionTypes 或constants 目录: const increment = 'counter/increment' const decrement = 'counter/decrement' export { increment, decrement } // -- // 使用: // actions/index.js import * as types from '../acitonTypes' const increment = payload => ({ type: types.increment, payload }) const decrement = payload => ({ type: types.decrement, payload }) // reducers/index.js import * as types from '../acitonTypes' const reducer = (state, action) => { switch (action.type) { case types.increment: return state + 1 case types.decrement: return state - action.payload default: return state } }
Note: Additional Action Type will complicate the project structure, this operation can be omitted. However, the domain/action
naming method is strongly recommended!
Separation and merging of Reducers
-
As project functionality becomes more complex, more and more state needs to be managed by Redux
-
At this point, there are two ways to handle state updates:
- Use one reducer: handle all state updates in the project
- Use multiple reducers: divided by project function, each function uses a reducer to handle the state update of the function
-
Recommendation: Use multiple reducers (the second solution) , each reducer handles a single state and clear responsibilities
-
At this time, there will be multiple reducers in the project, but the store can only receive one reducer . Therefore, multiple reducers need to be combined into one reducer before they can be passed to the store.
-
Merge method: use the
combineReducers
function in Redux -
Notice:
After merging, the state of Redux will become an object, and the structure of the object is the same as the parameter structure of the combineReducers function
- For example, the Redux state at this time is:
{ a: aReducer 处理的状态, b: bReducer 处理的状态}
- For example, the Redux state at this time is:
import { combineReducers } from 'redux' // 计数器案例,状态默认值为:0 const aReducer = (state = 0, action) => {} // Todos 案例,状态默认值为:[] const bReducer = (state = [], action) => {} // 合并多个reducer 为一个根reducer const rootReducer = combineReducers({ a: aReducer, b: bReducer }) // 创建store 时,传入根reducer const store = createStore(rootReducer) // 此时,合并后的redux 状态: { a: 0, b: [] }
-
Note: Although the state of the entire Redux application becomes an
对象
after usingcombineReducers
, for each reducer, each reducer is only responsible for a certain value in the entire state- That is: each reducer is only responsible for the state to be processed by itself
- Example:
- Login function: The state processed by the
loginReducer
should only be the state related to the login- Profile: The state handled by the
profileReducer
should only be the state related to the profile
- Profile: The state handled by the
- Login function: The state processed by the
- After the reducers are merged, the redux processing method: as long as the reducers are merged, no matter what action is distributed, all the reducers will be executed once. When each reducer is executing, it can process this action, and if it can’t process it, it returns to the previous state directly. Therefore, a certain action we distribute can only be processed by a certain reducer, that is, only the state to be processed by the reducer will be modified in the end. The final performance is: the action is distributed, and only the state corresponding to the action in redux is modified. !
What state does redux manage
How to handle different states:
- Put all the state in redux, managed by redux
- Only put some state data in redux, other data can be put in components, like:
- If a state is only used in a component (for example, the value of a form item), recommended: put it in the component
- The state that needs to be put into redux:
- Data to be used in multiple components [involving component communication]
- The interface data obtained through the ajax request [involving the question of where the request-related logic code is placed]
This article is reprinted from: https://www.iyouhun.com/post-228.html
This site is for inclusion only, and the copyright belongs to the original author.