• React数据管理Redux和thunk异步操作


    一、导语

    React 有旧版本的 createStore 和新版本的 configureStore,旧版本的已经不推荐使用,现对 configureStore 进行简单的使用说明。适用于类组件和函数组件。

    二、使用

    推荐官方教程: https://cn.redux.js.org/tutorials/quick-start/

    1、安装

    npm install @reduxjs/toolkit react-redux
    
    • 1

    安装 @reduxjs/toolkitreact-redux

    2、创建Redux Store

    第一步:在src文件夹下创建目录 store 在store中分别创建 index.jscounter_slice.js 两个文件。
    在 index.js 中

    import { configureStore } from '@reduxjs/toolkit'
    
    // counter_slice 相当于配置文件 名字随便取
    import counterSlice from "./counter_slice.js"
    
    // 将配置文件引入redux中。同理,若有其他文件也是一样的配置
    const store = configureStore({
        reducer: {
            counter: counterSlice,
        }
    })
    
    export default store
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在 counter_slice.js 中

    import { createSlice } from '@reduxjs/toolkit'
    
    // 创建数据和方法
    const counterSlice = createSlice({
    	// 名称 对应index.js 文件中的reducer对象中的key
        name: "counter", 
        // 初始化的数据
        initialState: {
            number: 0
        },
        // 方法 
        reducers: {
            add: (state, actions) => {
            	// actions 中有 type 和 payload 两个值
                // console.log(state, actions)
                state.number = actions.payload
            },
            sub: (state, actions) => {
                state.number = actions.payload
            }
        }
    })
    
    export const { add, sub } = counterSlice.actions // 暴露方法
    export default counterSlice.reducer // 导出reducer传给index.js
    
    • 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

    3、在项目入口引入Store

    src/index.js 中,通过 < Provider > 将 组件包裹起来,并将store作为prop传入。

    ...
    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import TodoList from './TodoList';
    import 'antd/dist/antd.css'; // 全局样式
    
    
    import { Provider } from 'react-redux';
    import store from './store'
    
    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(
        <Provider store={store}>
            <TodoList props="props-param"/>
        </Provider>
    );
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    4、在组件中使用和更新store

    在组件todolist.js 中

    • 引出store相关方法
    import { add, sub } from './store/counter_slice';
    import { useDispatch, useSelector } from 'react-redux';
    
    • 1
    • 2
    • 使用useSelector
        // 从 redux 取出 number 
        const number = useSelector((state) => {
            // console.log(state)
            return state.counter.number
    		
    		// counter 对应/src/store/index.js 文件中的counter
        })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 修改并更新store中的值
        const dispatch = useDispatch()
    
    	// 通过 dispatch 将更新值
        const handleAdd = () => {
            dispatch(add(inputValue))
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 完整的组件代码
    import React, { Fragment, useState, useEffect } from "react"
    import { add, sub } from './store/counter_slice';
    import { useDispatch, useSelector } from 'react-redux';
    // 引入样式文件
    import "./style.css"
      // 函数组件
    function TodoList(props) {
        const [inputValue, setInputValue] = useState("")
        const dispatch = useDispatch()
        const handleAdd = () => {
            dispatch(add(inputValue))
        }
        const handleInput = (e) => {
            const newValue = e.target.value
            setInputValue(newValue)
        }
        // 从 redux 取出 number
        const number = useSelector((state) => {
            // console.log(state)
            return state.counter.number
        })
        return (
            <div>
                <div>
                    <input value={inputValue} placeholder="input a value" style={{width: "300px" }} onChange={handleInput} />
                    <button type="primary" onClick={handleAdd}>更新</button>
                </div>
                <div>获取store中的值: {number}</div>
            </div>
        )
    }
    // 导出组件
    export default TodoList;
    
    • 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

    三、异步操作

    在操作数据的时候难免会遇到异步操作,React中用到的时候”中间件“的概念(thunk),理解起来较为复杂,具体的内容网上有专业的知识,此处简单讲解其中的一种使用方法。

    import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
    import axios from "axios"
    
    // 异步函数
    export const testFn = createAsyncThunk("counterSlice/testFn", async (param, api) => {
        // console.log(param, api)
        const { data } = await axios.get("http://bill.cc:3000/api/todolist1")
            return data
    })
    
    const counterSlice = createSlice({
        name: "counter",
        initialState: {
            number: 0
        },
        reducers: {
            add: (state, actions) => {
                // console.log(state, actions)
                state.number = actions.payload
                
            },
            sub: (state, actions) => {
                state.number = actions.payload
            }
        },
        // 异步处理
        extraReducers: {
        	// 异步promise发生success
            [testFn.fulfilled]: (state, actions) => {
                console.log(actions)
                state.number = actions.payload
            },
            // 异步promise发生rejected
            [testFn.rejected]: (state, actions) => {
                console.log(actions)
                state.number = "axios 请求发生错误"
            }
        }
    })
    
    export const { add, sub } = counterSlice.actions // 暴露方法(同步方法)
    export default counterSlice.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

    从 @reduxjs/toolkit 中导出 createAsyncThunk,用这个函数创建异步函数。
    在 createSlice 中的 extraReducers 接收异步函数 testFn 请求的结果并更新到store中。

    四、结束

    至此,store简单的使用介绍完毕,弄懂一遍第二遍就快很多。

  • 相关阅读:
    利用SVD对图像进行压缩
    辣椒碱人血清白蛋白纳米粒Capsaicin-HRP-HSA|辣椒素卵清白蛋白纳米粒Vanillylnonanamide-OVA|齐岳
    昨晚直播小鱼搞了个开源库之FishProtocol,目前已经两颗星
    创建 Edge 浏览器扩展教程(下)
    网络安全(黑客)自学
    LQ0264 鲁卡斯队列【精度计算】
    数据库系统概论的一些知识点
    MFC CDockablePane类,常见配置
    深入理解线程安全
    python实现选择排序算法
  • 原文地址:https://blog.csdn.net/qq_43706089/article/details/126850434