react|redux状态管理
参考官网:https://cn.redux-toolkit.js.org/tutorials/quick-start
状态管理使用流程
1、安装:
npm install react-redux @reduxjs/toolkit
2、创建store.js
通过configureStore的hook对reducer(或slice)进行统一管理。
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from '../features/counter/counterSlice';export const store = configureStore({reducer: {counter: counterReducer,// ...},
});
3、编写我们的Reducer(或slice)
通过createSlice创建slice;需要创建异步的action方法的时候需要引入createAsyncThunk的hook。
createSlice核心属性:name、initialState、reducers、extraReducers。
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { fetchCount } from './counterAPI';const initialState = {value: 0,status: 'idle',
};// 下面的函数称为thunk,它允许我们执行异步逻辑。
// 它可以像常规操作一样被调度:'dispatch(incrementAsync(10))'。
// 这将使用'dispatch'函数作为第一个参数来调用thunk。
// 然后可以执行异步代码,并可以分派其他操作。
// Thunks 通常用于发出异步请求.
export const incrementAsync = createAsyncThunk('counter/fetchCount',async (amount) => {const response = await fetchCount(amount);// 我们返回的值成为“已完成”的操作负载(action.payload)return response.data;}
);export const counterSlice = createSlice({name: 'counter',initialState,// 'reducers'字段允许我们定义reducers并生成相关的操作(action)reducers: {increment: (state) => {// Redux Toolkit允许我们在reducer中编写“状态变化”的逻辑。 // 它实际上不会改变状态,因为它使用了Immer库,// 它检测到“状态”的变化,并根据这些变化产生一个全新的不可变状态state.value += 1;},decrement: (state) => {state.value -= 1;},// 使用PayloadAction类型来声明' action.payload '的内容。incrementByAmount: (state, action) => {state.value += action.payload;},},// 'extraReducers'字段允许切片处理在其他地方定义的动作,// 包括由createAsyncThunk或其他切片生成的动作。extraReducers: (builder) => {builder.addCase(incrementAsync.pending, (state) => {state.status = 'loading';}).addCase(incrementAsync.fulfilled, (state, action) => {state.status = 'idle';state.value += action.payload;});},
});export const { increment, decrement, incrementByAmount } = counterSlice.actions;// 下面的函数被称为选择器,它允许我们从状态中选择一个值。
// 选择器也可以内联定义,而不是在片文件中使用。
// 比如: `useSelector((state: RootState) => state.counter.value)`
export const selectCount = (state) => state.counter.value;// 我们也可以手工编写脚本,其中可能包含同步和异步逻辑。
// 下面是一个基于当前状态有条件地调度操作的示例。
export const incrementIfOdd = (amount) => (dispatch, getState) => {const currentValue = selectCount(getState());if (currentValue % 2 === 1) {dispatch(incrementByAmount(amount));}
};export default counterSlice.reducer;
4、提供redux store给react
使用Provider高阶组件包裹App,并传递store属性。
import React from 'react'
import ReactDOM from 'react-dom/client'
import './index.css'
import App from './App'// 提供redux store给react,需要引入的工具store、provider
import store from './app/store'
import { Provider } from 'react-redux'// As of React 18
const root = ReactDOM.createRoot(document.getElementById('root'))root.render(<Provider store={store}><App /></Provider>
)
5、react组件中操作redux的state和action
通过redux提供的useSelector和useDispatch的hook去操作state和action即可。
import './App.css';import { useSelector, useDispatch } from 'react-redux';
import { incremented, decremented } from './store/slices/counterSlice';function App() {const count = useSelector((state) => {return state.value;});const dispatch = useDispatch();return (<div className="App"><header className="App-header"><h3>count: {count}</h3><div><button style={{width: '130px',height: '40px',fontSize: '20px',cursor: 'pointer',marginRight: '10px'}} onClick={() => dispatch(incremented())}>incremented</button><button style={{width: '130px',height: '40px',cursor: 'pointer',fontSize: '20px'}} onClick={() => dispatch(decremented())}>decremented</button></div><p>Edit <code>src/App.js</code> and save to reload.</p></header></div>);
}export default App;