react redux用法学习

发布于:2025-02-13 ⋅ 阅读:(17) ⋅ 点赞:(0)

参考资料:
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
          }
        }
      }
    }

未完待续