1 2
| npm i redux react-redux @reduxjs/toolkit npm i --save-dev @types/react-redux
|
基本概念
单向数据流(one way data flow)
- state负责管理数据
- 只有通过Actions才能修改数据
- 基于state渲染view


不可变性
- state 只读, 只有通过Actions才能修改state
Action特点:
- 本质就是一个普通JS对象
- 内部必须要有一个描述事件的Type属性
- 多数情况下type为string类型
- 除了type属性必须要有其他任意
- 只是描述事件,但未指明如何更新state
Reducer:
- 本质是函数,负责相应Actions并按规定修改数据.
Store
- 将actions和reducer联系到一起
主要职责
- 维持应用的state
- 提供getState获取状态
- 提供dispatch 修改数据
- 通过subscribe()注册监听
- 通过unsubscribe()注销监听
- state状态:
- DomianState: 服务器返回的state
- UI state: 关于当前组件的State
- App state: 全局的State
执行流程
- 创建描述事件的普通action对象,然后将该对象dispatch到store中(执行dispatch)
- store接收到action后悔调用根reducer方法,让其根据action和旧state计算新的state
- 最后,store会通知subscribers 状态更新.
官方例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| 1. 创建初始state const initialState={ value:10 }
2. 定义reducer方法
function counterReducer(state = initialState, action) { switch (action.type) { case 'counter/incremented': return { ...state, value: state.value + 1 } case 'counter/decremented': return { ...state, value: state.value - 1 } default: return state } }
3. 通过createStore创建store export const store = createStore(counterReducer)
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import { Provider } from 'react-redux'; import {store} from "./store/counterSlice";
const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement ); root.render( <Provider store={store}> <App /> </Provider> );
import React,{FC} from 'react' import {useDispatch,} from "react-redux"; import {increment,decrement} from "../store/counterSlice"; import { Button } from "antd"
export const Fc:FC = (Props) => { const dispatch = useDispatch(); return( <> <Button onClick={()=>dispatch(increment())}>add</Button> - <Button onClick={()=>dispatch(decrement())}>minus</Button> </> )
}
|
搭配@reduxjs/toolkit使用
createStore 已被废弃,官方推荐使用configureStore
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| import {createStore} from 'redux' import {configureStore, createAction, createReducer, createSlice, PayloadAction} from "@reduxjs/toolkit"; import {IAction} from "../types"; import {AnyAsyncThunk} from "@reduxjs/toolkit/dist/matchers";
const defaultState = 0 const reducer01 = (state = defaultState, action: IAction<any>) => { switch (action.type) { case 'INCREMENT': return state + 1 case 'DECREMENT': return state - 1 default: return state } }
export const store01 = createStore(reducer01)
const increment = createAction<number>('INCREMENT'); const decrement = createAction<number>('DECREMENT'); const reducer02 = createReducer(defaultState, { [increment.type]: (state, action:PayloadAction<any>) => state + action.payload, [decrement.type]: (state, action) => state - action.payload }) export const store02 = configureStore({ reducer: reducer02 }) const exampleSlice = createSlice({ name: 'example', initialState: defaultState, reducers: { INCREMENT: (state, action) => state + action.payload, DECREMENT: (state, action) => state - action.payload
} })
export const {INCREMENT, DECREMENT} = exampleSlice.actions; export const store03 = configureStore({ reducer: exampleSlice.reducer })
|