Redux使用详解(三)--Redux Toolkit

Redux

认识Redux Toolkit

Redux Toolkit 是官方推荐的编写 Redux 逻辑的方法。
在前面我们学习Redux的时候应该已经发现,redux的编写逻辑过于的繁琐和麻烦。
并且代码通常分拆在多个文件中(虽然也可以放到一个文件管理,但是代码量过多,不利于管理);
Redux Toolkit包旨在成为编写Redux逻辑的标准方式,从而解决上面提到的问题;
在很多地方为了称呼方便,也将之称为“RTK”;
安装Redux Toolkit
npm install @reduxjs/toolkit react-redux

Redux Toolkit的核心API主要是如下几个:
configureStore:包装createStore以提供简化的配置选项和良好的默认值。它可以自动组合你的 slice reducer,添加你提供
的任何 Redux 中间件,redux-thunk默认包含,并启用 Redux DevTools Extension。
createSlice:接受reducer函数的对象、切片名称和初始状态值,并自动生成切片reducer,并带有相应的actions。
createAsyncThunk: 接受一个动作类型字符串和一个返回承诺的函数,并生成一个pending/fulfilled/rejected基于该承诺分
派动作类型的 thunk

重构之前的代码-创建counter的reducer

我们先对counter的reducer进行重构: 通过createSlice创建一个slice。
createSlice主要包含如下几个参数:
name:用户标记slice的名词
在之后的redux-devtool中会显示对应的名词;
initialState:初始化值
第一次初始化时的值;
reducers:相当于之前的reducer函数
对象类型,并且可以添加很多的函数;
函数类似于redux原来reducer中的一个case语句;
函数的参数:
参数一:state
参数二:调用这个action时,传递的action参数;
createSlice返回值是一个对象,包含所有的actions;

import { createSlice } from "@reduxjs/toolkit"

const counterSlice = createSlice({
  name: "counter",
  initialState: {
    counter: 888
  },
  reducers: {
    addNumber(state, { payload }) {
      state.counter = state.counter + payload
    },
    subNumber(state, { payload }) {
      state.counter = state.counter - payload
    }
  }
})

export const { addNumber, subNumber } = counterSlice.actions
export default counterSlice.reducer

store的创建

configureStore用于创建store对象,常见参数如下:
reducer,将slice中的reducer可以组成一个对象传入此处;
middleware:可以使用参数,传入其他的中间件;
devTools:是否配置devTools工具,默认为true;

import { configureStore } from "@reduxjs/toolkit"

import counterReducer from "./features/counter"
import homeReducer from "./features/home"

const store = configureStore({
  reducer: {
    counter: counterReducer,
    home: homeReducer
  }
})

export default store

Redux Toolkit的异步操作

在之前的开发中,我们通过redux-thunk中间件让dispatch中可以进行异步操作。
Redux Toolkit默认已经给我们继承了Thunk相关的功能:createAsyncThunk

export const getHomeMultidataAction = createAsyncThunk('a/b', async (extraInfo, { dispatch, getState }) => {
	const res = await axios.get('http://..../a/b')
	return res.data.data
})

当createAsyncThunk创建出来的action被dispatch时,会存在三种状态
pending: action被发出,但是还没有最终的结果。
fulfilled: 获取到最终的结果(如果由返回值的结果)
rejected: 执行过程中由错误或者抛出了异常

我们可以在createSlice的entraReducder中监视这些结果

extraReducers: {
	[getHomeMultidataAction.pending](state, action) {
		console.log("getHomeMultidataAction pending", action)
	},
	[getHomeMultidataAction.fulfilled](state, {payload}) {
		console.log("getHomeMultidataAction fuilfilled", payload)
		state.banners = payload.banner.list
		state.recommends = payload.recommend.list		
	},
	[getHomeMultidataAction.rejected](state, action){
		console.log("getHomeMultidataAction rejected", action)
	}
}

extraReducer的另外一种写法
extraReducer还可以传入一个函数,函数接受一个builder参数。
我们可以向builder中添加case来监听异步操作的结果:

extraReducers: (builder) => {
	builder.addCase(getHomeMultidataAction.pending, (state) => {
		console.log("getHomeMultidataAction pending")
	}).addCase(getHomeMultidataAction.fulfilled, (state,{payload}) => {
		state.banners = payload.banner.list
		state.recommends = payload.recommend.list
	})
}

useSelector() 与 useDispatch()

useSelector()用来加载state中的数据
useDispatch()来获取派发器对象

store.js中

//使用RTK来构建store
import {configureStore, createSlice} from "@reduxjs/toolkit";

// createSlice 创建reducer的切片
// 它需要一个配置对象作为参数,通过对象的不同的属性来指定它的配置
const stuSlice = createSlice({
    name:'stu', // 用来自动生成action中的type
    initialState:{
        name:'孙悟空',
        age:18,
        gender:'男',
        address:'花果山'
    }, // state的初始值
    reducers:{ // 指定state的各种操作,直接在对象中添加方法
        setName(state, action){
            // 可以通过不同的方法来指定对state的不同操作
            // 两个参数:state 这个state的是一个代理对象,可以直接修改
            state.name = action.payload;
        },
        setAge(state, action){
            state.age = action.payload;
        }
    }
});

// 切片对象会自动的帮助我们生成action
// actions中存储的是slice自动生成action创建器(函数),调用函数后会自动创建action对象
// action对象的结构 {type:name/函数名, payload:函数的参数}
export const {setName, setAge} = stuSlice.actions;

// 创建store 用来创建store对象,需要一个配置对象作为参数
const store = configureStore({
   reducer:{
       student:stuSlice.reducer
   }
});

export default store;

app.js中

import React from 'react';
import {useDispatch, useSelector} from "react-redux";
import {setName, setAge} from './store';

const App = () => {
    // useSelector() 用来加载state中的数据
    const student = useSelector(state => state.student);
    //另一种写法
    const {student} = useSelector(state => state)
    // 通过useDispatch()来获取派发器对象
    const dispatch = useDispatch();
    // 获取action的构建器


    const setNameHandler = () => {
        dispatch(setName('沙和尚'));
    };

    const setAgeHandler = () => {
        dispatch(setAge(33));
    };

    return (
        <div>
            <p>
                {student.name} ---
                {student.age} ---
                {student.gender} ---
                {student.address}
            </p>
            <button onClick={setNameHandler}>修改name</button>
            <button onClick={setAgeHandler}>修改age</button>
        </div>
    );
};

export default App;

app.js中

import ReactDOM from "react-dom/client";
import App from "./App";
import {Provider} from "react-redux";
import store from './store';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <Provider store={store}>
        <App/>
    </Provider>
);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_聪明勇敢有力气

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值