react redux用法学习
参考资料:
https://www.bilibili.com/video/BV1ZB4y1Z7o8
https://cn.redux.js.org/tutorials/essentials/part-5-async-logic
AI工具:deepseek,通义灵码
安装相关依赖:
使用redux的中间件:
npm i react-redux
react-redux 并不是另一个 redux,而是对 redux 做了封装
npm i @reduxjs/toolkit
更好的使用 react-redux 的工具
构建目录
示例代码
index.js
import { configureStore } from "@reduxjs/toolkit";import channelReducer from "./modules/channelStore";const store = configureStore({reducer: {channelReducer: channelReducer,}
})export default store;
modules/xxx.js
import { createSlice } from "@reduxjs/toolkit";import { getStoreList } from "../../utils/http";const counterSlice = createSlice({name: "counter",initialState: {channelList: [], },reducers: {setChannel(state, action) {// 不能计算随机值,因为reducer是纯函数,不能有副作用state.channelList = action.payload},setChannel1: {reducer(state, action) {console.log("state -- ", state)console.log("action -- ", action)// state.push(action.payload)},prepare(title, content) {console.log("title -- ", title)console.log("content -- ", content)return {payload: {id: 1,title,content}}}}}
})const { setChannel, setChannel1 } = channelSlice.actions// 方法1
const fetchChannlList = async (dispatch) => {const response = await getStoreList()dispatch(setChannel(response.data.businessList))
}// 方法2
const fetchChannlList2 = () => async (dispatch) => {dispatch(setChannel1(1, 2))// const response = await getStoreList()// dispatch(setChannel(response.data.businessList))
}export {fetchChannlList,fetchChannlList2
};const reducer = channelSlice.reducer;export default reducer;
xxx.js为 modules 内独立redux模块
reducer内不要有类似生成随机数的逻辑,保证纯函数
reducers内的reducer可以是函数写法,也可以对象写法。对象写法会有reducer 与 prepare这两个回调函数可供使用。
prepare为该 setChannel1 获取的参数的收束,可在其中加工参数,生成随机数return
reducer为该 setChannel1 原参数,state、action
xxx.jsx
import { useSelector, useDispatch } from "react-redux";
import { useEffect } from 'react';import styles from './demo.module.css'import {fetchChannlList,fetchChannlList2
} from '../../store/modules/channelStore'const Demo = () => {const {channelList} = useSelector(state => state.channelReducer);const dispatch = useDispatch();useEffect(() => {// 方法1fetchChannlList(dispatch)// 方法2dispatch(fetchChannlList2())}, [])return (<div><h1>Hello World1</h1><p>Hello World</p><ul>{channelList.map(item => {return <li key={item.businessId}>{item.storeName}</li>})}</ul></div>)
}export default Demo;
其中 useSelector 可获取 redux 的 state,useDispatch 可触发 redux 的 action 修改 state。
代码中 方法2 是官网推荐方法,及将reducer的action引到jsx后,将方法放到dispatch里调用,reducer的异步方法为:
const fetchChannlList2 = () => async (dispatch) => {// dispatch(setChannel1(1, 2))const response = await getStoreList()dispatch(setChannel(response.data.businessList))
}
其中dispatch会在第二次回调中给出来
而 方法1 是我尝试使用的,reducer的异步方法为:
const fetchChannlList = async (dispatch) => {const response = await getStoreList()dispatch(setChannel(response.data.businessList))
}
fetchChannlList 直接就拿到了dispatch
目前得到的结果都是一致的
后续学习中再寻找方法2 比 方法1 更推荐的原因。
反思问题
为什么 reducer 不能生成随机数,在我多次实验与查询后,生成随机数可能会有一下影响:
1.无法做test,没办法做断言测试(纯函数可做断言)
2.reducer中产生随机数可能导致组件多次更新,消耗更多性能
3.使用谷歌tool的时间旅行时,如果reducer中使用类似随机数逻辑可能导致 tool无法定位问题
未完待续