我是靠谱客的博主 细腻星星,这篇文章主要介绍【Redux】的封装以及使用(6),现在分享给大家,希望可以做个参考。

文章目录

    • 二、 语法
        • 1. 获取数据
        • 2. 修改数据
    • 三、模块化
    • 四、异步解决
        • 1. 问题
        • 2. redux-thunk


## 一、 基本配置
  1. 安装 redux 和 react-redux
复制代码
1
2
npm i redux react-redux --save
  1. src 下创建 store 目录,新建 index.ts
复制代码
1
2
3
4
5
6
7
8
9
// 导入 redux 中的 legacy_createStore 来创建状态管理仓库 import { legacy_createStore} from "redux"; import reducer from "./reducer"; // window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() 让浏览器redux-dev-tools能正常使用 const store = legacy_createStore(reducer,window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()); export default store
  1. 创建一个提供数据的 reducer.tsx
复制代码
1
2
3
4
5
6
7
8
9
10
11
// 初始化 state const initialState = { num: 20, } export default (state = initialState) => { // 将传递的数据进行深拷贝 let newState = JSON.parse(JSON.stringify(initialState)) // 返回 state return newState }
  1. main.tsx 文件中通过 Provider 组件进行包裹 App 组件进行提供数据
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 通过 provider 提供数据 import { Provider } from 'react-redux' import store from '@/store' ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( // Provider 给所有组件提供 store 里的数据 <Provider store={store}> <React.StrictMode> <BrowserRouter> <App /> </BrowserRouter> </React.StrictMode> </Provider>, )

二、 语法

1. 获取数据

复制代码
1
2
3
4
import { useSelector } from 'react-redux' // 通过 useSelector 方法,获取返回的 state 中的数据 const { num } = useSelector((state: { num: number }) => ({ num: state.num }))

2. 修改数据

复制代码
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
// reducer.tsx export default (state = initialState, action: { type: string; val: any }) => { // 将传递的数据进行深拷贝 let newState = JSON.parse(JSON.stringify(state)) // 根据传递的标记执行对应的操作 switch (action.type) { case 'add': newState.num++ break case 'add2': newState.num += action.val break default: break } // 返回 state return newState } // page.tsx import { useSelector, useDispatch } from 'react-redux' // 通过 useDispatch 方法,修改 state 中的数据 const dispatch = useDispatch() const changeNum = () => { // type 固定属性对应触发的函数名 // val 自定义的属性 // 该方法执行后 reducer 中的会对传递的 type 值进行判断执行对应的操作 // dispatch({ type: 'add' }) dispatch({ type: 'add2', val: 7 }) }

三、模块化

  1. store 文件夹下创建对应的模块文件夹
  2. 模块文件下创建 index(管理数据)和 reducer(处理数据) 文件
复制代码
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
// 模块1 index const store = { state: { num: 18, }, actions: { add(state: { num: any }, action: object) { state.num++ }, }, } export default store // 模块2 index const store = { state: { num: 20, }, actions: { add2(state: { num: any }, { type, val }: any) { state.num += val }, }, } export default store // reducer import store from '.' export default ( state = { ...store.state }, action: { type: string; val: any }, ) => { // 将传递的数据进行深拷贝 let newState = JSON.parse(JSON.stringify(state)) // 遍历存储的方法 for (let key in store.actions) { // 判断传递的方法在 store 中是否存在 if (action.type === key) { // 存在则调用对应的方法 store.actions[key](newState, action) break } } // 返回 state return newState }
  1. store 文件夹下的 index 文件将模块进行整合、注册
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { combineReducers, legacy_createStore } from 'redux' // reducer 导入准备的数据 import reducer1 from './Data/reducer' import reducer2 from './Data1/reducer' // 组个各个模块的 reducer const reducers = combineReducers({ reducer1, reducer2, }) // 创建数据仓库,注册 reducer const store = legacy_createStore( reducers, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(), ) // 导出 export default store
  1. 访问的话通过 useSelector 方法返回对应 模块 的数据(state.模块名.xxx)
复制代码
1
2
3
4
5
6
7
8
9
10
// 通过 useSelector 方法,获取返回的 state 中的数据 const { num } = useSelector((state: RootState) => ({ // 模块1的 num num: state.reducer1.num, })) const { num: num2 } = useSelector((state: RootState) => ({ // 模块2的 num num: state.reducer2.num, }))

四、异步解决

1. 问题

  1. 在store/NumStatus/index.ts中做异步操作
  2. 会发现这种写法其实达不到想要的异步效果
  3. 需要通过 redux 相关的异步方案来解决
复制代码
1
2
3
4
5
6
7
8
add1(newState:{num:number},action:{type:string}){ //newState.num++; // 会有bug 没有办法达到延迟和修改的效果 setTimeout(()=>{ newState.num++; },1000) },

2. redux-thunk

  1. 市面上有redux- saga , redux-thunk,redux-thunk相比于redux-saga ,体积小,灵活,但需要自己手动抽取和封装。但学习成本较低。

  2. 安装:npm i redux-thunk

  3. 让 redux 调式工具兼容异步

  4. 导入 applyMiddleware、compose 方法将仓库数据、reduxTools、reduxThunk 进行关联

  5. dispatch 方法传递一个执行异步的回调

  6. 执行回调中传递的参数,根据 tyep 标记去匹配需要执行的方法

复制代码
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
61
62
63
64
65
// store/index import { combineReducers, legacy_createStore, compose, applyMiddleware, } from 'redux' // reducer 导入准备的数据 import reducer1 from './Data/reducer' import reducer2 from './Data1/reducer' import reduxThunk from 'redux-thunk' // 组个各个模块的 reducer const reducers = combineReducers({ reducer1, reducer2, }) // 让 redux 调式工具兼容异步的处理 let composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose // 把仓库数据,浏览器redux-dev-tools,还有reduxThunk插件关联在store中 const store = legacy_createStore( reducers, composeEnhancers(applyMiddleware(reduxThunk)), ) // 导出 export default store // page import store from '@/store/Data' // 异步的写法 redux-thunk 的用法 dispatch(异步执行的函数) // disp 相当于 dispatch 用来标记调用的函数 // dispatch((disp: Function) => { // setTimeout(() => { // disp({ type: 'add' }) // }, 0) // }) // 优化 redux-thunk 的异步方法 // dispatch(调用状态管理中的 asyncAdd) dispatch(store.asyncFun.asyncAdd) // Data/index { state: { num: 18, }, actions: { add(state: { num: number }, action: object) { state.num++ }, }, // 优化 redux-thunk 的异步方法(模仿 vuex 写法 ) // 存放异步的方法 asyncFun: { asyncAdd(disp: Function) { setTimeout(() => { disp({ type: 'add' }) }, 1000) }, }, }

最后

以上就是细腻星星最近收集整理的关于【Redux】的封装以及使用(6)的全部内容,更多相关【Redux】内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(82)

评论列表共有 0 条评论

立即
投稿
返回
顶部