React--》Redux Toolkit的使用讲解

news2024/11/29 10:52:49

目录

Redux Toolkit

redux toolkit的基本使用

RTK代码模块化

RTK QUERY的使用

useQuery参数


Redux Toolkit

Redux Toolkit是Redux的工具包,简称RTK,可以帮助我们处理使用Redux过程中的重复性工作,简化Redux中的各种操作,当然博主也不可能将RTK讲解的面面俱到,看完本篇文章后还是推荐大家多多看一下 官方文档 ,无论是RTK还是Redux,在React中使用 react-redux 都是必不可少的,所以使用RTK依然需要安装两个包,如下:

npm install react-redux @reduxjs/toolkit

redux toolkit的基本使用

官方已经给出我们使用redux toolkit的基本示例了,如下图所示,在这里我结合官方给出的示例简单的说明并讲解一下函数的使用。

根据官方给出的基础案例,在src文件夹下新建文件夹store,然后新建index.jsx文件,并写出如下代码:

// 使用RTK创建store, createSlice 创建reducer的切片
import { configureStore, createSlice } from "@reduxjs/toolkit";
const stuSlice = createSlice({ // 需要一个配置对象作为参数,通过对象的不同属性来指定它的配置
  name:'stu', // 用来自动生成 action 中的 type
  initialState:{ // state的初始值
    name:"张三",
    age:18,
    gender:"男",
    address:"北京"
  },
  // 指定state的各种操作,直接在对象中添加方法
  reducers:{
    setName: state => { // state是一个代理对象,可直接修改
      state.name = "李四"
    },
    setAge: state => {
      state.age = 28
    }
  }
})
// 切片对象会自动的帮助我们生成action
export const { setName,setAge } = stuSlice.actions
// 创建store,用来创建store对象,需要一个配置对象作为参数
const store = configureStore({
  reducer:{
    student:stuSlice.reducer
  }
})
export default store

要想在全局使用store文件中定义的数据和方法,需要在入口文件main.js文件中进行如下操作:

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

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

接下里通过调用redux相关api来获取数据和方法。

import { useSelector,useDispatch } from "react-redux"
import { setName,setAge } from "./store"
const App = () => {
  // useSelector() 用来加载state中的数据
  const student = useSelector(state => state.student)
  // 通过useDispatch() 来获取派发器对象
  const dispatch = useDispatch()
  const changeName = () =>{ 
    dispatch(setName())
  }
  const changeAge = () =>{ 
    dispatch(setAge())    
  }
  return (
    <div>
      <p>{student.name}--{student.age}--{student.gender}--{student.address}</p>
      <button onClick={changeName}>修改名字</button>
      <button onClick={changeAge}>修改年龄</button>
    </div>
  )
}
export default App

如果想通过传参的方式进行修改数据的话,可以采用以下这种方式:

RTK代码模块化

因为state的数据可能不止一种,将每一种数据都存放在store的一个文件中就会显得代码特别的臃肿,后期难以维护,为了便于今后的管理,可以对RTK代码进行模块化划分,也就是说,每一个数据都有单独的文件,最后所有的文件都整合到store文件夹下的index文件中,如下:

将我设置好的两个store数据单独抽离出去:

import { createSlice } from "@reduxjs/toolkit";
// 创建学生切片
const stuSlice = createSlice({ // 需要一个配置对象作为参数,通过对象的不同属性来指定它的配置
  name:'stu', // 用来自动生成 action 中的 type
  initialState:{ // state的初始值
    name:"张三",
    age:18,
    gender:"男",
    address:"北京"
  },
  // 指定state的各种操作,直接在对象中添加方法
  reducers:{
    setName: (state,action) => { // state是一个代理对象,可直接修改
      state.name = action.payload
    },
    setAge: (state,action) => {
      state.age = action.payload
    }
  }
})
// 切片对象会自动的帮助我们生成action
export const { setName,setAge } = stuSlice.actions
export const { reducer:stuReducer } = stuSlice
import { createSlice } from "@reduxjs/toolkit";
// 创建学校切片
const schoolSlice = createSlice({
  name:"school",
  initialState:{
    name:'北京大学',
    address:'北京市',
  },
  reducers:{
    setName: (state,action) => {
      state.name = action.payload
    },
    setAddress: (state,action) => {
      state.address = action.payload
    }
  }
})
export const { setName,setAddress } = schoolSlice.actions
export const { reducer:schoolReducers  } = schoolSlice

将抽离出去的数据都存放在store文件夹下的index.jsx文件中,如下:

// 使用RTK创建store,用于管理所有数据的文件
import { configureStore } from "@reduxjs/toolkit"; 
import { stuReducer } from "./student";
import { schoolReducers } from "./school";

// 创建store,用来创建store对象,需要一个配置对象作为参数
const store = configureStore({
  reducer:{
    student:stuReducer,
    school:schoolReducers
  }
})
export default store

在相关组件中调用该store中的数据:

import { useSelector,useDispatch } from "react-redux"
import { setName,setAge } from "./store/student"
import { setAddress,setName as setSchoolName } from "./store/school"

const App = () => {
  // useSelector() 用来加载state中的数据
  const { student,school } = useSelector(state => state)
  // 通过useDispatch() 来获取派发器对象
  const dispatch = useDispatch()
  const changeName = () =>{ 
    dispatch(setName("王五"))
  }
  const changeAge = () =>{ 
    dispatch(setAge(30))    
  }
  const changeSchoolName = () =>{ 
    dispatch(setSchoolName("五道口职业技术学院"))
  }
  const changeSchoolAddress = () =>{ 
    dispatch(setAddress("海淀区"))
  }
  return (
    <div>
      <h2>个人信息:</h2>
      <p>{student.name}--{student.age}--{student.gender}--{student.address}</p>
      <button onClick={changeName}>修改个人名字</button>
      <button onClick={changeAge}>修改个人年龄</button>
      <h2>学校信息:</h2>
      <p>{school.name}--{school.address}</p>
      <button onClick={changeSchoolName}>修改学校名字</button>
      <button onClick={changeSchoolAddress}>修改学校地址</button>
    </div>
  )
}
export default App

可以看到上文进行抽离的代码给人的感觉是十分干练整洁的,十分便于维护,结果如下:

RTK QUERY的使用

RTK不仅帮助我们解决了state问题,同时它还为我们提供了RTK Query用来帮助我们处理数据加载问题,RTK Query是一个强大的数据获取和缓存工具,在它的帮助下,Web应用中的加载变得十分简单,它使我们不再需要自己编写虎丘数据和缓存数据的逻辑。

要知道在Web应用中加载数据时需要处理的问题

1)根据不同的加载状态显示不同的UI组件

2)减少对相同数据重复发送请求

3)使用乐观更新,提示用户体验

4)在用户与UI交互时,管理缓存的声明周期

这些问题RTKQ都可以帮助我们处理,首先可以直接通过RTKQ向服务器发送请求加载数据,并且RTKQ会自动对数据进行缓存,避免重复发送不必要的请求,其次RTKQ在发送请求时会根据请求不同的状态返回不同的值,我们可以通过这些值来监视请求发送的过程并随时中止

RTKQ已经继承在了RTK中,如果我们已经在项目中引入了RTK则无需再引入其余的模块,如果你不想使用RTKQ给我们提供的发送请求的方式(简单封装过的fetch),需要自己引入要使用的发送请求的工具。ok接下来开始讲解如何使用RTKQ,如下:

在store文件中新建一个word文件用于获取名言警句的接口,如下:

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' 

// 创建Api对象,createApi()用来创建RTKQ中的API对象
const wordApi = createApi({
  reducerPath:'wordApi', // Api的标识,不能和其他的Api或reducer重复
  baseQuery: fetchBaseQuery({ // 指定查询的基础信息,发送请求使用的工具
    baseUrl:"https://api.uixsj.cn/"
  }), 
  // build是请求的构造器,通过build来设置请求的相关信息
  endpoints(build){
    return {
      getStudents:build.query({
        query(){
          // 用来指定请求的子路径
          return 'hitokoto/get' 
        }
      })
    }
  }
})

// Api对象创建后,对象中会根据各种方法自动是生成对应的钩子函数,通过这些钩子函数,可向服务器发送请求
// 钩子函数的命名规则 getStudents --> useGetStudentsQuery
export const { useGetStudentsQuery } = wordApi
export default wordApi

填写完接口文件后,在store文件夹下的index.jsx文件中进行引入:

import { configureStore } from "@reduxjs/toolkit";
import wordApi from "./word";

const store = configureStore({
  reducer:{
    [wordApi.reducerPath]:wordApi.reducer
  },
  // 添加一个中间件,这个中间件已自动生成了我们直接引入即可,中间件用来处理Api缓存
  middleware:getDefaultMiddleware => {
    return getDefaultMiddleware().concat(wordApi.middleware)
  }
})

export default store

当然这里的话我们也需要在入口文件中进行store传入:

接下来开始使用我们创建的钩子函数进行相关数据的调用,如下:

currentData:undefined  // 当前参数的最新数据

data:undefined              // 最新的数据

isError:false                  // 布尔值,是否有错误

error:Error()                  // 对象,有错时才存在

isFetching:true             // 布尔值,数据是否在加载

isLoading:true              // 布尔值,数据第一次加载成功

isSuccess:false            // 布尔值,请求是否成功

isUninitialized:false      // 布尔值,请求是否还没有开始发送

refetch:f()                     // 一个函数,用来重新加载数据

status:"pending"          // 字符串,请求的状态

因为我调用的接口没有data数据,数据在error中,这里的话需要我们在error进行数据的获取:

import { useGetStudentsQuery } from './store/word'

const App = () => {
  // 调用Api查询数据,这个钩子函数它会返回一个对象作为返回值,请求过程中相关数据都在该对象中
  const {isError,error,isLoading} = useGetStudentsQuery()
  return (
    <div>
      { isLoading && <p>数据加载中...</p> }
      {isError && error.data}
    </div>
  )
}

export default App

如果接收的接口数据有很多,但自己只是想要其中的一小部分,可以通过以下方式解决:

useQuery参数

RTKQ给我们提供对接收到的数据进行自定义设置,如下:

import { useGetStudentsQuery } from './store/word'

const App = () => {
  // 调用Api查询数据,这个钩子函数它会返回一个对象作为返回值,请求过程中相关数据都在该对象中
  const result = useGetStudentsQuery(null,{
    // useQuery可以接收一个对象作为第二个参数,通过该对象可以对请求进行配置
    selectFromResult:result => { // 用来指定useQuery返回的结果
      if(result.data === undefined){
        result.data = '值被我修改了'
      }
      return result
    },
    pollingInterval:0, // 设置轮询的间隔(隔一段时间发起一次请求),单位毫秒,如果为0则不轮询
    skip:false, // 设置是否跳过当前请求,默认为false
    refetchOnMountOrArgChange:false, // 设置是否每次都重新加载数据,false正常使用缓存;true每次都重载数据;数字,数据缓存的时间(秒)
  })
  console.log(result)
  const {isError,error,isLoading} = result
  return (
    <div>
      { isLoading && <p>数据加载中...</p> }
      {isError && error.data}
    </div>
  )
}

还有两个参数设置需要在store进行数据监听才能使用,如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/474030.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

< 每日小技巧: 基于Vue状态的过渡动画 - Transition 和 TransitionGroup>

》基于Vue状态的过渡动画 - Transition 和 TransitionGroup &#x1f449; 一、Vue Transition 简介> Transition 和 TransitionGroup 之间的区别 &#x1f449; 二、<Transition> 组件> 触发 <Transition> 组件的场景&#xff1a;> 基于 CSS 的过渡效果&…

LeetCode:面试题 02.07. 链表相交

&#x1f34e;道阻且长&#xff0c;行则将至。&#x1f353; &#x1f33b;算法&#xff0c;不如说它是一种思考方式&#x1f340; 算法专栏&#xff1a; &#x1f449;&#x1f3fb;123 题解目录 一、&#x1f331;[面试题 02.07. 链表相交](https://leetcode.cn/problems/in…

Python可视化学习——使用JSON进行数据转换、pyecharts模块调用以及可视化案例的介绍(可视化案例数据暂无),柱状图及动态柱状图的构建

数据可视化 可视化效果一&#xff1a;2020年印美日新冠累计确诊人数 2020年是新冠疫情爆发的一年&#xff0c;随着疫情的爆发&#xff0c;国内外确诊人数成了大家关心的热点&#xff0c;相信大家都有看过类似的疫情报告.本案例对印度美国日本三个国家确诊人数的进行了可视化处…

术数基础背诵口诀整理

物象对应 五行方位天干神兽季节气候星宿生成数脏器木东甲乙青龙春风岁八肝火南丙丁朱雀夏热荧惑七心土中戊己&#xff1f;长夏湿镇五脾金西庚辛白虎秋燥太白九肺水北壬癸玄武冬寒辰六肾 口诀&#xff1a;东方甲乙青龙木&#xff0c;南方丙丁朱雀火&#xff0c;戊己勾陈腾蛇土&…

第一章 Java基础 50 道面试题

文章目录 前言匿名内部类访问的局部变量为什么必须要用final修饰? Java基础1、jdk和jre有什么区别&#xff1f;2、final在Java中有什么作用&#xff1f;3、有常量类了为什么还要使用枚举类&#xff1f;4、为什么使用包装类&#xff1f;5、和equals的区别是什么&#xff1f;6、…

Mysql-最左前缀法则以及索引失效情况

最左前缀法则 如果索引了多列&#xff08;联合索引&#xff09;&#xff0c;要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始&#xff0c;并且不跳过索引中的列。如果跳跃某一列&#xff0c;索引将会部分失效(后面的字段索引失效)。 以 tb_user 表为例&#xff…

前端面试题(持续更新中)

【1】null和undefined的区别 同&#xff1a; 1.都是js的基本类型&#xff0c;保存在栈中&#xff0c;表示“无、没有”的意思。 2.if语句中的null和undefined都是false。 var a undefined var b null if (!a) {console.log(undefined is false); } if (!b) {console.log(null…

YOLOv7如何提高目标检测的速度和精度,基于模型结构、数据增强提高目标检测速度

目录 一、基于模型结构的方法1、多尺度训练和测试2、更细的特征图3、重新设计的损失函数 二、基于数据增强的方法1、随机缩放和裁剪2、随机旋转和翻转3、随机亮度和对比度调整4、随机噪声和模糊处理 三、实验结果与分析1、数据集和实验设置2、实验结果的分析和比较 大家好&…

【VM服务管家】VM4.0软件使用_1.1 环境配置类

目录 1.1.1 驱动配置&#xff1a;图像后台切换但前端界面不变的解决方法1.1.2 驱动缺失&#xff1a;格式化工具打开后消失的解决方法1.1.3 环境配置&#xff1a;VM试用版本激活报错的解决方法1.1.4 模块数限制&#xff1a;修改VM最大模块数量1.1.5 开机自启动&#xff1a;VM运行…

【VM服务管家】VM4.0平台SDK_2.3 控件嵌入类

目录 2.3.1 渲染结果&#xff1a;通过绑定流程或模块获取渲染结果的方法2.3.2 渲染控件&#xff1a;渲染控件加载本地图像的方法2.3.3 渲染控件&#xff1a;渲染控件上自定义图形的方法2.3.4 参数控件&#xff1a;参数配置控件绑定模块的方法2.3.5 控件颜色&#xff1a;控件颜色…

【AGC】质量服务数据分析问题

【关键字】 AGC、质量、数据分析 【问题描述】 开发者反馈在应用中集成了AGC的相关服务&#xff0c;在查看平台数据时遇到了一些问题。具体如下所述&#xff1a; 我发现平台的App卸载量每个月都非常高&#xff0c;卸载量/新下载量近80%&#xff0c;很异常&#xff0c;所以想…

【VM服务管家】VM4.x算子SDK开发_3.2 公用工具类

目录 3.2.1 图像载入&#xff1a;本地图像的载入方法3.2.2 相机取流&#xff1a;相机SDK取流的方法3.2.3 输入图像&#xff1a;给算子模块输入图像数据的方法3.2.4 实时取流&#xff1a;实时取流的实现方法3.2.5 卡尺ROI&#xff1a;卡尺型ROI的生成方法3.2.6 DL算子耗时&#…

【VM服务管家】VM4.2软件使用_5.3 环境配置类

目录 1.1.1 用户权限&#xff1a;普通用户权限使用VM的方法1.1.2 脚本环境&#xff1a;联合OpenCV开发的环境配置方法1.1.3 环境配置&#xff1a;规避流程运行时卡死的方法 1.1.1 用户权限&#xff1a;普通用户权限使用VM的方法 描述 环境&#xff1a;VM4.2 现象&#xff1a;生…

JPA实战

常见 ORM 框架 **Mybatis(ibatis)&#xff1a;**一款优秀的持久层框架&#xff0c;它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息&#xff0c;将接口和 …

【深圳】IBM V3500存储维修 更换控制器故障

冠峰科技-爱科技爱分享 今天给大家分享的是深圳.福田区一个电商客户公司一台IBM Storwize v3500存储控制器故障从远程诊断 收集日志 分析结果的实际案例&#xff0c;如图所示通过存储管理口登陆进去后直接看到少了一个控制器&#xff0c; 按照惯例&#xff0c;还是得登陆到服…

linux智能网关4G离散数据采集分析HDMI广告牌

数字城市的4G边缘计算网关是一种具有强大处理能力、智能控制和现场数据采集能力的计算设备。其主要特点包括以下方面&#xff1a; 系统平台&#xff1a;基于Linux或Debian系统&#xff0c;可灵活开发各种应用程序。IO接口&#xff1a;2DI、2DO数字输入输出接口&#xff0c;可以…

JAVASE的全面总结

&#xff08;未完待续&#xff09; 五、子类与继承 5.1 子类与父类 继承是一种由已有的类创建新类的机制。利用继承&#xff0c;我们可以先创建一个共有属性的一般类&#xff0c;根据该一般类再创建具有特殊属性的新类&#xff0c;新类继承一般类的状态和行为&#xff0c;并…

golang - switch

switch 的使用 switch 语句用于基于不同条件执行不同操作&#xff0c;&#xff0c;直每一个 case 分支都是唯一的&#xff0c;从上到下逐一测试到匹配为止匹配项后面也不需要再加 break switch 表达式 {case 表达式1, 表达式2, ... :语句块1case 表达式2, 表达式3, ... :语句块…

Linux LD链接器 -静、动库编译or链接

文章目录 程序链接动态链接静态链接 目标文件链接打包为动态打包为静态总结 动态链接- 动态链接&#xff1a;在运行、加载时&#xff0c;在内存中完成链接的过程- 动态共享库&#xff1a;用于动态链接的系统库、特性是可以加载无需重定位的代码 got表(Global Offset Table)延时…

SpringBoot核心配置全面总结

目录 1、application. properties核心文件 2、 application.yml配置文件&#xff08;推荐配置风格&#xff09; 3、SpringBoot多环境配置 4、SpringBoot自定义配置 1&#xff09;Value注解 2&#xff09; ConfigurationProperties 5. 远程配置中心&#xff08;目前生产…