第三节:Redux Toolkit 使用详解 和 RTK的异步操作

一. Redux Toolkit详解

1. 简介

(1).Redux Toolkit 是官方推荐的编写 Redux 逻辑的方法。

  在前面我们学习Redux的时候应该已经发现,redux的编写逻辑过于的繁琐和麻烦。

  并且代码通常分拆在多个文件中(虽然也可以放到一个文件管理,但是代码量过多,不利于管理);

  Redux Toolkit包旨在成为编写Redux逻辑的标准方式,从而解决上面提到的问题;

  在很多地方为了称呼方便,也将之称为“RTK”;

(2).需要安装下面两个包

  【npm install @reduxjs/toolkit react-redux】

(3).Redux Toolkit的核心API主要是如下几个:

  configureStore:包装createStore以提供简化的配置选项和良好的默认值。它可以自动组合你的 slice reducer,添加你提供的任何 Redux 中间件,redux-thunk默认包含,并启用 Redux DevTools Extension。

  createSlice:接受reducer函数的对象、切片名称和初始状态值,并自动生成切片reducer,并带有相应的actions。

  createAsyncThunk: 接受一个动作类型字符串和一个返回承诺的函数,并生成一个pending/fulfilled/rejected基于该承诺分派动作类型的 thunk

 

2. createSlice剖析

(1) createSlice主要包含如下几个参数:

 ◼ name:用户标记slice的名词: 在之后的redux-devtool中会显示对应的名词;

 ◼ initialState:初始化值,第一次初始化时的值;

 ◼ reducers:相当于之前的reducer函数

  对象类型,并且可以添加很多的函数; 函数类似于redux原来reducer中的一个case语句; 函数的参数:

  ✓ 参数一:state

  ✓ 参数二:调用这个action时,传递的action参数;

(2) 返回值

 ◼ createSlice返回值是一个对象,包含所有的actions;

 

3. configureStore剖析

用于创建store对象,常见参数如下:

  reducer,将slice中的reducer可以组成一个对象传入此处;

  middleware:可以使用参数,传入其他的中间件(自行了解);

  devTools:是否配置devTools工具,默认为true;

详见:store/index.js

 

4. 实操

 (1). 安装相关的包  【npm install react-redux @reduxjs/toolkit 】

 (2). 在count.js 和 home1.js 中通过createSlice配置初始化数据和reducer,然后对外导出action和reducer

import { createSlice } from '@reduxjs/toolkit';

const countSlice = createSlice({
	name: 'myCount',
	initialState: {
		counter: 100,
	},
	// 这个的reducer相当于之前单独的reducer中switch的逻辑
	reducers: {
		addNumberAction(state, action) {
			state.counter = state.counter + action.payload;
		},
		// payload是对action的解构
		subNumberAction(state, { payload }) {
			state.counter = state.counter - payload;
		},
	},
});

// 对外导出reducer的方法 和 reducer

// 解构的同时对外导出
export const { addNumberAction, subNumberAction } = countSlice.actions;
export default countSlice.reducer;

 (3). 在store/index.js 中通过 configureStore 配置多个reducer,这里给子reducer命名,如: ypfCount,后续调用的时候要使用

import { configureStore } from '@reduxjs/toolkit';
import countReducer from './count';
import homeReducer from './home2';

const store = configureStore({
	reducer: {
		ypfCount: countReducer,
		ypfHome: homeReducer,
	},
	// 是否配置devTools工具,默认为true;
	devTools: true,
});

export default store;

 (4). 在pages文件夹下的 zAbout组件、zCateGory2组件中进行store数据的使用

   A. 导入各种reducer中的action

   B. 通过 mapStateToProps 和 mapDispatchToProps 进行数据和方法映射

 

二.  RTK异步操作

1. 写法1---写法简洁,个人喜欢

  (1). 通过Redux Toolkit默认已经给我们继承了Thunk相关的功能:createAsyncThunk,在其内部发送请求,获取数据。

  (2). 直接通过 dispatch(xxxAction) 修改store里的数据

详见:  store/home1.js

需要把:zCategory2中的引用改为: ../store/home1

            store/index.js中的引用改为:../store/home1

查看代码
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import axios from 'axios';

const homeSlice = createSlice({
	name: 'myHome',
	initialState: {
		banners: [],
		recommends: [],
	},
	reducers: {
		changeBannersAction(state, action) {
			state.banners = action.payload;
		},
		//这里的payload是对action的解构
		changeRecommendsAction(state, { payload }) {
			state.recommends = payload;
		},
	},
});

// 异步操作需要单独处理--createAsyncThunk
// 写法1: 直接使用dispatch修改store里的数据
export const fetchHomeMultidataAction = createAsyncThunk('GetHomeData', async (extraInfo, { dispatch, getState }) => {
	// 1.发送网络请求, 获取数据
	const res = await axios.get('http://xxx:8000/home/multidata');

	// 2.取出数据, 并且在此处直接dispatch操作(可以不做)
	const banners = res.data.data.banner.list;
	const recommends = res.data.data.recommend.list;

	// 下面两个dispathch可以直接修改赋值,就不用写下面的extraReducer了
	dispatch(changeBannersAction(banners));
	dispatch(changeRecommendsAction(recommends));
});

// 对外导出
// 解构的同时对外导出
export const { changeBannersAction, changeRecommendsAction } = homeSlice.actions;
export default homeSlice.reducer;

 

2. 写法2--官方推荐的

  (1). 通过Redux Toolkit默认已经给我们继承了Thunk相关的功能:createAsyncThunk,在其内部发送请求,获取数据。

  (2). 通过createSlice中的extraReducers进行监听状态,可以写成计算属性的模式 或 函数的模式,有三种状态

     pending:action被发出,但是还没有最终的结果;

     fulfilled:获取到最终的结果(有返回值的结果);

     rejected:执行过程中有错误或者抛出了异常;

  (3). 另外需要配合 createAsyncThunk 中返回数据

详见:  store/home2.js

需要把:zCategory2中的引用改为: ../store/home2

            store/index.js中的引用改为:../store/home2 

查看代码
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import axios from 'axios';

// 异步操作需要单独处理--createAsyncThunk
// 写法2: 使用homeSlice中的extraReducers进行监听
export const fetchHomeMultidataAction = createAsyncThunk('GetHomeData', async (extraInfo, { dispatch, getState }) => {
	// 1.发送网络请求, 获取数据
	const res = await axios.get('http://xxx:8000/home/multidata');
	// 2. 返回数据
	return res.data;
});

const homeSlice = createSlice({
	name: 'myHome',
	initialState: {
		banners: [],
		recommends: [],
	},
	reducers: {
		changeBannersAction(state, action) {
			state.banners = action.payload;
		},
		//这里的payload是对action的解构
		changeRecommendsAction(state, { payload }) {
			state.recommends = payload;
		},
	},
	// extraReducers--计算属性的写法
	// 为了简便,可以只监听成功的状态fulfilled,解构出来的payLoad就是上述fetchHomeMultidataAction返回的数据res.data
	/* 	extraReducers: {
		[fetchHomeMultidataAction.pending](state, action) {
			console.log('fetchHomeMultidataAction.pending');
		},
		// payLoad是对action的解构
		[fetchHomeMultidataAction.fulfilled](state, { payload }) {
			state.banners = payload.data.banner.list;
			state.recommends = payload.data.recommend.list;
		},
		[fetchHomeMultidataAction.rejected](state, action) {
			console.log('fetchHomeMultidataAction.pending');
		},
	}, */
	// extraReducers--函数写法
	extraReducers: (builder) => {
		builder
			.addCase(fetchHomeMultidataAction.pending, (state, action) => {
				console.log('fetchHomeMultidataAction pending');
			})
			.addCase(fetchHomeMultidataAction.fulfilled, (state, { payload }) => {
				state.banners = payload.data.banner.list;
				state.recommends = payload.data.recommend.list;
			});
	},
});

// 对外导出
// 解构的同时对外导出
export const { changeBannersAction, changeRecommendsAction } = homeSlice.actions;
export default homeSlice.reducer;

 

 

 

 

 

 

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 
posted @ 2023-05-06 11:03  Yaopengfei  阅读(807)  评论(1编辑  收藏  举报