参考资料:
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(() => {
// 方法1
fetchChannlList(dispatch)
// 方法2
dispatch(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无法定位问题
第二天
就上述问题:方法2 比 方法1 更推荐的原因
// 方法1
fetchChannlList(dispatch)
// 方法2
dispatch(fetchChannlList2())
当使用方法1时,下面reducer只会触发reducer,而不会走prepare的逻辑
而当使用方法2时,入参会先进入prepare后通过return,进入reducer
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
}
}
}
}
未完待续