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
//store 文件
1. 创建初始state
const initialState={
value:10
}

2. 定义reducer方法
//type 字段需要唯一,因为这是每个action对应的唯一名称.
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)


// index.ts文件
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 进行包裹
<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";

/**
* 使用默认createStore
*/
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
})