React(react18)中组件通信06------redux-toolkit + react-redux
-
- [1 前言](#1 前言)
- [1.1 redux 和 react-redux](#1.1 redux 和 react-redux)
- [1.2 关于redux-toolkit](#1.2 关于redux-toolkit)
-
- [1.2.1 官网](#1.2.1 官网)
- [1.2.2 为什么要用Redux Toolkit?](#1.2.2 为什么要用Redux Toolkit?)
- [1.3 安装 Redux Toolkit](#1.3 安装 Redux Toolkit)
- [1.4 Redux Toolkit相关API](#1.4 Redux Toolkit相关API)
- [2. 开始例子------官网例子](#2. 开始例子——官网例子)
-
- [2.1 创建 Redux Store](#2.1 创建 Redux Store)
- [2.2 为 React 提供 Redux Store](#2.2 为 React 提供 Redux Store)
- [2.3 创建 Redux State Slice](#2.3 创建 Redux State Slice)
-
- [2.3.1 counterSlice.js文件](#2.3.1 counterSlice.js文件)
- [2.3.2 对比之前的action 和 reducer](#2.3.2 对比之前的action 和 reducer)
- [2.4 添加 Slice Reducers 到 Store](#2.4 添加 Slice Reducers 到 Store)
- [2.5 在 React 组件中使用 Redux State 和 Actions](#2.5 在 React 组件中使用 Redux State 和 Actions)
- [2.6 渲染](#2.6 渲染)
- [2.7 效果](#2.7 效果)
-
- [2.7.1 效果展示](#2.7.1 效果展示)
- [2.7.2 说明](#2.7.2 说明)
- [2.8 注意:](#2.8 注意:)
- [2.9 附代码](#2.9 附代码)
- [3. 例子2------练手小例子](#3. 例子2——练手小例子)
-
- [3.1 再添加一个Dog组件](#3.1 再添加一个Dog组件)
- [3.1.1 编写 dogSlice](#3.1.1 编写 dogSlice)
-
- [3.1.2 修改store.js](#3.1.2 修改store.js)
- [3.1.3 编写dog组件](#3.1.3 编写dog组件)
- [3.1.4 效果](#3.1.4 效果)
- [3.2 这数据共享也太简单了吧](#3.2 这数据共享也太简单了吧)
-
- [3.2.1 试试数据共享](#3.2.1 试试数据共享)
- [3.2.2 react-redux + redux 数据共享](#3.2.2 react-redux + redux 数据共享)
- [4. 关于 Payload------载荷payload](#4. 关于 Payload——载荷payload)
- [5. 项目代码](#5. 项目代码)
-
- [5.1 代码目录](#5.1 代码目录)
- [5.2 下载项目](#5.2 下载项目)
1 前言
1.1 redux 和 react-redux
- 前面两篇文章已经介绍过了,需要的可以点进去看看:
React(react18)中组件通信04------redux入门.
React(react18)中组件通信05------redux ➕ react-redux(含数据共享).
1.2 关于redux-toolkit
1.2.1 官网
1.2.2 为什么要用Redux Toolkit?
- 首先看官网怎么说?
- 然后看我们代码中createStore已经被弃用了,如下:
1.3 安装 Redux Toolkit
-
安装命令如下
javascriptnpm install @reduxjs/toolkit yarn add @reduxjs/toolkit
-
如果项目没有装过react-redux,可以两个一起安装,但是不用单独安装 redux 了,
react-redux + redux-toolkit
替换了react-redux + redux
bashnpm install @reduxjs/toolkit react-redux yarn add @reduxjs/toolkit react-redux
1.4 Redux Toolkit相关API
-
先简单介绍几个
-
官网全,还是看官网吧
2. 开始例子------官网例子
- 过程参考官方下面的地址:
https://cn.react-redux.js.org/tutorials/quick-start/.
2.1 创建 Redux Store
-
从 Redux Toolkit 中导入 configureStore API。我们将开始创建一个空的 Redux store,并导出它,如下:
javascriptimport { configureStore } from '@reduxjs/toolkit'; export default configureStore({ reducer: { }, });
-
这将创建一个 Redux store,并自动配置 Redux DevTools 扩展,以便你可以在开发时检查 store。
2.2 为 React 提供 Redux Store
- 这个按照原先的保持不变就行,如下:
2.3 创建 Redux State Slice
2.3.1 counterSlice.js文件
- 创建 slice 需要一个字符串名称来标识 slice,一个初始 state 值,以及一个或多个 reducer 函数来定义如何更新 state。创建 slice 后,我们可以导出生成的 Redux action creators 和整个 slice reducer 函数。
- 如下:
2.3.2 对比之前的action 和 reducer
-
之前的action写法,如下:
javascriptfunction incrementOne(){ type:'INCREMENT_ONE' } function incrementNumber(number){ type:'INCREMENT_NUMBER', number:number } export default{incrementOne,incrementNumber}
-
之前的reducer写法,如下
javascriptfunction countReducer(state = 0,action){ switch (action.type) { case 'INCREMENT_ONE': return state + 1; case 'INCREMENT_NUMBER': return state + action.number; default: return state; } } export default{countReducer}
2.4 添加 Slice Reducers 到 Store
- 接下来,我们需要从 counter slice 中导入 reducer 函数并将其添加到我们的 store 中。通过在 reducers 参数中定义一个字段,我们告诉 store 使用这个 slice reducer 函数来处理该 state 的所有更新。
- 所以最后的
store.js
,如下:
2.5 在 React 组件中使用 Redux State 和 Actions
- 现在我们可以使用 React Redux hooks 让 React 组件与 Redux store 交互。我们可以使用 useSelector从 store 中读取数据(不通过props了),并使用
useDispatch
dispatch actions。 - 组件内设计如下:
2.6 渲染
- 一样的代码
2.7 效果
2.7.1 效果展示
- 如下:
2.7.2 说明
- 单击 【点我+1】 、 【点我-1】和【加数】按钮:
对应的 Redux action 会被 dispatch 到 store;
计数 slice reducer 将看到 actions 更新其 state;
<Counter>
组件将从 store 中看到新的 state 值,并使用新的数据重新渲染自己。
2.8 注意:
- 如下:
2.9 附代码
-
counterSlice.js
javascriptimport {createSlice} from '@reduxjs/toolkit' export const counterSlice = createSlice({ name: 'myFirstCounterSlice', //这个名字随便取 标识 initialState: { value: 0, //初始值 }, reducers: { // 对比之前的reducer是一个函数,里面是根据不同的action的type判断的switch语句 incrementOne: (state) =>{ //下面生成 加 1 的action,等价于原先只有type的action state.value += 1; }, decrementOne: (state) =>{ //下面生成 减 1 的action,等价于原先只有type的action state.value -= 1; },incrementNumber: (state,action) =>{ //等价于不只有type一个参数的action state.value += action.payload; //payload } } }); // 为每个 case reducer 函数生成 Action creators export const {incrementOne,decrementOne,incrementNumber} = counterSlice.actions; const countReducer = counterSlice.reducer; export default countReducer;
-
store.js
javascriptimport { configureStore } from '@reduxjs/toolkit'; import countReducer from './reducerAndAction/counterSlice'; export default configureStore({ reducer: { counterState: countReducer, }, });
-
Counter.jsx
javascriptimport {useRef} from "react"; import { useDispatch, useSelector } from 'react-redux' import {incrementOne,decrementOne,incrementNumber} from '../redux/reducerAndAction/counterSlice' function Couter(){ // console.log(props); const numberRef = useRef(); const count = useSelector((state)=>state.counterState.value); const dispatch = useDispatch(); //加 1 的 function addOne(){ dispatch(incrementOne()); } //动态增加 function addNumber(){ const stringNumber = numberRef.current.value; //直接取取的是字符串 const number = parseInt(stringNumber); const addNumberAction = incrementNumber(number); //有参数的action dispatch(addNumberAction); } return( <div> 当前数值是:{count} <br /> <button onClick={addOne}>点我+1</button> <button onClick={()=>dispatch(decrementOne())}>点我-1</button> <br /><br /> <input type="number" ref={numberRef} placeholder="请输入要加的数"/> <button onClick={addNumber}>加数</button> </div> ) } export default Couter;
3. 例子2------练手小例子
3.1 再添加一个Dog组件
3.1.1 编写 dogSlice
- 如下:
3.1.2 修改store.js
- 如下:
3.1.3 编写dog组件
- 为了方便,添加就简单写了,需要的自行优化,如下:
3.1.4 效果
- 如下:
3.2 这数据共享也太简单了吧
3.2.1 试试数据共享
- 直接访问试试,代码如下:
- 还真行,这可比redux + react-redux 简单太多了,效果如下
3.2.2 react-redux + redux 数据共享
- 关于react-redux + redux 数据共享怎么实现的数据共享,需要的看下面的文章,如下:
React(react18)中组件通信05------redux ➕ react-redux(含数据共享).
4. 关于 Payload------载荷payload
-
关于
state.value += action.payload; //payload
,下面举个例子,如果还用原先的redux的话,action也可以如下写法:
-
再比如, "新增一个待办事项" 的 Action创造函数,你可以这么写:
javascriptvar id = 1 function addTodo(content) { return { type: 'ADD_TODO', payload: { id: id++, content: content, // 待办事项内容 completed: false // 是否完成的标识 } } }
-
这就可以理解
action.payload
为啥要这么用,为了规范呗,不管你传的是什么参数,数字还是对象,都是action.payload
,看一下我们上面的例子就更好理解了,如下:
5. 项目代码
5.1 代码目录
- 如下: