Redux的简介及其在React中的应用

Redux

Redux 是React最常用的集中状态管理工具,类似于Vue中的Pinia(Vuex),可以独立于框架运行

作用:通过集中管理的方式管理应用的状态。

使用步骤:

  1. 定义一个 reducer 函数 (根据当前想要做的修改返回一个新的状态);

  2. 使用createStore方法传入 reducer函数 生成一个store实例对象

  3. 使用store实例的 subscribe方法 订阅数据的变化(数据一旦变化,可以得到通知);

  4. 使用store实例的 dispatch方法提交action对象 触发数据变化(告诉reducer你想怎么改数据);

  5. 使用store实例的 getState方法 获取最新的状态数据更新到视图中。

 管理数据流程:

为了职责清晰,数据流向明确,Redux把整个数据修改的流程分成了三个核心概念,分别是:state、action和reducer

  1. state:一个对象 存放着我们管理的数据状态;

  2. action:一个对象 用来描述你想怎么改数据;

  3. reducer:一个函数 根据action的描述生成一个新的state。

 Redux与React环境准备

配套工具

在React中使用redux,官方要求安装俩个其他插件 - Redux Toolkit 和 react-redux

  1. Redux Toolkit(RTK)- 官方推荐编写Redux逻辑的方式,是一套工具的集合集,简化书写方式

  2. react-redux - 用来 链接 Redux 和 React组件 的中间件。

配置基础环境

  1. 使用 CRA 快速创建 React 项目

    npx create-react-app react-redux
  2. 安装配套工具

    npm i @reduxjs/toolkit react-redux
  3. 启动项目

    npm run start

store目录结构设计

 

  1. 通常集中状态管理的部分都会单独创建一个单独的 store 目录

  2. 应用通常会有很多个子store模块,所以创建一个 modules 目录,在内部编写业务分类的子store

  3. store中的入口文件 index.js 的作用是组合modules中所有的子模块,并导出store

Redux与React 实现counter

 

使用React Toolkit 创建counterStore
// src => store => modules => counterStore.js
import { createSlice } from '@reduxjs/toolkit'const counterStore = createSlice({name: 'counter',//模块的名称// 初始化stateinitialState: {count: 0},// 修改数据的方法,都是同步方法,支持直接修改reducers: {incremnent(state) {state.count++},decrement(state) {state.count--}}
})// 解构出来actionCreater函数
const { incremnent, decrement } = counterStore.actions
// 获取reducer
const reducer = counterStore.reducer// 以按需导出的方式导出actionCreater
export { incremnent, decrement }
// 以默认导出的方式导出reducer
export default reducer
// src => store => index.js
import { configureStore } from "@reduxjs/toolkit";
// 导入子模块reducer
import counterReducer from "./modules/counterStore";const store = configureStore({reducer: {counter: counterReducer}
})export default store
为React注入store

react-redux负责把Redux和React 链接 起来,内置 Provider组件 通过 store 参数把创建好的store实例注入到应用中,链接正式建立。

// src => index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import store from './store';
import { Provider } from 'react-redux';const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<React.StrictMode><Provider store={store}><App /></Provider></React.StrictMode>
);// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
React组件使用store中的数据

在React组件中使用store中的数据,需要用到一个 钩子函数 - useSelector,它的作用是把store中的数据映射到组件中,使用样例如下:

import { useSelector } from 'react-redux'
function App() {const { count } = useSelector(state => state.counter)return (<div className="App">{count}</div>);
}
export default App;

React组件修改store中的数据

React组件中修改store中的数据需要借助另外一个hook函数 - useDispatch,它的作用是生成提交action对象的dispatch函数,使用样例如下:

import { useSelector, useDispatch } from 'react-redux'
// 导入actionCreater
import { incremnent, decrement } from './store/modules/counterStore'
function App() {const { count } = useSelector(state => state.counter)const dispathc = useDispatch()return (<div className="App"><button onClick={() => dispathc(decrement())}>-</button>{count}<button onClick={() => dispathc(incremnent())}>+</button></div>);
}
export default App;
Redux与React 提交action传参
  • 需求说明:

    组件中有俩个按钮 add to 10add to 20 可以直接把count值修改到对应的数字,目标count值是在组件中传递过去的,需要在提交action的时候传递参数

  • 提交action传参实现需求:

    • 在reducers的同步修改方法中添加action对象参数

    • 调用actionCreater的时候传递参数,参数会被传递到action对象payload属性上。

// src => app.js
import { useSelector, useDispatch } from 'react-redux'
// 导入actionCreater
import { incremnent, decrement, addToNum } from './store/modules/counterStore'
function App() {const { count } = useSelector(state => state.counter)const dispathc = useDispatch()return (<div className="App"><button onClick={() => dispathc(decrement(10))}>-</button>{count}<button onClick={() => dispathc(incremnent(10))}>+</button><button onClick={() => dispathc(addToNum(10))}>add to 10</button><button onClick={() => dispathc(addToNum(20))}>add to 20</button></div>);
}
export default App;
// src => store => counterStore.js
import { createSlice } from '@reduxjs/toolkit'
const counterStore = createSlice({name: 'counter',//模块的名称// 初始化stateinitialState: {count: 0},// 修改数据的方法,都是同步方法,支持直接修改reducers: {incremnent(state) {state.count++},decrement(state) {state.count--},addToNum(state, actions) {state.count = actions.payload}}
})
// 解构出来actionCreater函数
const { incremnent, decrement, addToNum } = counterStore.actions
// 获取reducer
const reducer = counterStore.reducer
// 以按需导出的方式导出actionCreater
export { incremnent, decrement, addToNum }
// 以默认导出的方式导出reducer
export default reducer
Redux与React 异步状态操作

 异步操作步骤:

  1. 创建store的写法保持不变,配置好同步修改状态的方法;

  2. 单独封装一个函数,在函数内部return一个新函数,在新函数中;

    2.1 封装异步请求获取数据;

    2.2 调用同步actionCreater传入异步数据生成一个action对象,并使用dispatch提交。

  3. 组件中dispatch的写法保持不变。

import { useSelector, useDispatch } from 'react-redux'
// 导入actionCreater
import { incremnent, decrement, addToNum } from './store/modules/counterStore'
import { useEffect } from 'react'
import { fetchChannelList } from './store/modules/channelStore'
function App() {const { count } = useSelector(state => state.counter)const { channelList } = useSelector(state => state.channel)const dispathc = useDispatch()// 使用useEffect触发异步请求执行useEffect(() => {dispathc(fetchChannelList())}, [])return (<div className="App"><button onClick={() => dispathc(decrement(10))}>-</button>{count}<button onClick={() => dispathc(incremnent(10))}>+</button><button onClick={() => dispathc(addToNum(10))}>add to 10</button><button onClick={() => dispathc(addToNum(20))}>add to 20</button><ul>{channelList.map((item) => (<li key={item.id}>{item.name}</li>))}</ul></div>);
}
export default App;
// src => store => modules => channelStore
import { createSlice } from "@reduxjs/toolkit";
import axios from "axios";
const channelStore = createSlice({name: 'channel',initialState: {channelList: []},reducers: {setChannels(state, actions) {state.channelList = actions.payload}}
})
// 异步请求部分
const { setChannels } = channelStore.actions
const fetchChannelList = () => {return async (dispathc) => {const res = await axios.get('http://geek.itheima.net/v1_0/channels')dispathc(setChannels(res.data.data.channels))}
}
export { fetchChannelList }
const reducer = channelStore.reducer
export default reducer

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

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

相关文章

Maven的安装配置

文章目录 一、MVN 的下载二、配置maven2.1、更改maven/conf/settings.xml配置2.2、配置环境变量一、MVN 的下载 还是那句话,要去就去官网或者github,别的地方不要去下载。我们下载binaries/ 目录下的 cd /opt/server wget https://downloads.apache.org/maven/maven-3/3.9.6/…

如何找到捏蛋糕和修牛蹄类型的解压视频素材?

今天&#xff0c;我们来聊一个让人放松的话题——如何找到捏蛋糕和修牛蹄类型的解压视频素材。你是否也曾在抖音、快手上被这些视频吸引&#xff1f;它们确实让人倍感舒适。如果你也想制作这种类型的解压视频&#xff0c;下面我将推荐几个优秀的网站&#xff0c;帮助你快速找到…

锂电池储能电站火灾危险及对策分析

引言 随着风能和太阳能等可再生能源在能源结构中所占比例的持续增长&#xff0c;以及对间歇性和波动性能源接入需求的增加&#xff0c;加之锂电池成本的降低&#xff0c;锂电池储能电站正在新能源并网和电力系统辅助服务等多个领域得到广泛应用。然而&#xff0c;随着锂电池储…

【ddnsgo+ipv6】

ddnsgoipv6 DNS解析添加记录ddnsgo配置 DNS解析添加记录 ddnsgo配置

Go的环境搭建以及GoLand安装教程

目录 一、开发环境Golang安装 二、配置环境变量 三、GoLand安装 四、Go 语言的 Hello World 一、开发环境Golang安装 官方网址&#xff1a; The Go Programming Language 1. 首先进入官网&#xff0c;点击Download&#xff0c;选择版本并进行下载&#xff1a; ​ ​ 2. …

论文概览 |《IJGIS》2024.09 Vol.38 issue9

本次给大家整理的是《International Journal of Geographical Information Science》杂志2024年第38卷第9期的论文的题目和摘要&#xff0c;一共包括9篇SCI论文&#xff01; 论文1 A movement-aware measure for trajectory similarity and its application for ride-sharing …

伦敦金行情分析及策略:突破交易及其止损

突破一直是伦敦金市场中重要的策略&#xff0c;但由于智能交易越来越成为很多主流机构所使用的交易工具&#xff0c;参与突破交易的朋友经常成为输家&#xff0c;因为他们的行动被捕捉到了。那这个突破的伦敦金行情分析及策略是不是不能用呢&#xff1f;也不是&#xff0c;下面…

MFC中Excel的导入以及使用步骤

参考地址 在需要对EXCEL表进行操作的类中添加以下头文件&#xff1a;若出现大量错误将其放入stdafx.h中 #include "resource.h" // 主符号 #include "CWorkbook.h" //单个工作簿 #include "CRange.h" //区域类&#xff0c;对Excel大…

实验(未完成)

一、拓扑图 二、需求及分析 1、需求 按照图示的VLAN及IP地址需求&#xff0c;完成相关配置。 要求SW1为VLAN 2/3的主根及主网关&#xff0c;SW2为VLAN 20/30的主根及主网关。 SW1和SW2互为备份。 可以使用super vlan。 上层通过静态路由协议完成数据通信过程。 AR1为企…

导航栏及下拉菜单的实现

这次作业我们将来实现下图&#xff1a; 主要有导航栏及下拉菜单组成 编写代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style>* {margin: 0;padding: 0;/* border: 1px solid red; */}.menu…

Vue2 doc、excel、pdf、ppt、txt、图片以及视频等在线预览

Vue2 doc、excel、pdf、ppt、txt、图片等在线预览 安装使用目录结构直接上代码src\components\FileView\doc\index.vuesrc\components\FileView\excel\index.vuesrc\components\FileView\img\index.vuesrc\components\FileView\pdf\index.vuesrc\components\FileView\ppt\index…

js,ts控制流程

摘要&#xff1a; 在 JavaScript 和 TypeScript 中&#xff0c;控制流程是指程序执行的顺序和条件判断。以下是一些常见的控制流程结构&#xff0c;包括条件语句、循环语句和函数调用等。 1. 条件语句&#xff1a; if 语句 let condition true;if (condition) {console.log(C…

如何利用谷歌浏览器提升上网体验

在当今数字化时代&#xff0c;拥有一款高效、便捷且个性化的浏览器对于提升上网体验至关重要。谷歌浏览器作为全球最受欢迎的浏览器之一&#xff0c;凭借其强大的功能和简洁的界面设计&#xff0c;赢得了广大用户的青睐。本文将为您介绍三个实用技巧&#xff0c;帮助您更好地利…

敏捷开发新助力:超越传统的10大知识库工具

敏捷开发强调快速响应变化、持续交付价值以及团队之间的紧密协作。为了实现这些目标&#xff0c;团队需要借助高效、智能的知识库工具来管理、整合和分享项目中的各类知识资源。以下是敏捷开发团队必备的10大知识库工具&#xff0c;其中特别包含了HelpLook AI知识库。 HelpLook…

计算机网络——SDN

分布式控制路由 集中式控制路由

C语言——VS实用调试技巧

文章目录 什么是bug&#xff1f;什么是调试&#xff08;debug&#xff09;&#xff1f;debug和releaseVS调试快捷键环境准备调试快捷键 监视和内存观察监视内存 调试举例1调试举例2调试举例3&#xff1a;扫雷编程常见错误归类编译型错误链接型错误运行时错误 什么是bug&#xf…

对称二叉树(力扣101)

题目如下: 思路 对于这道题, 我会采用递归的解法. 看着对称的二叉树, 写下判断对称的条件, 再进入递归即可. 值得注意的是, 代码中会有两个函数, 第一个是isSymmetric,第二个是judge. 因为这里会考虑到一种特殊情况, 那就是 二叉树的根结点(最上面的那个),它会单独用…

gitee 使用 webhoot 触发 Jenkins 自动构建

一、插件下载和配置 Manage Jenkins>Plugin Manager 搜索 gitee 进行安装 插件配置 1、前往Jenkins -> Manage Jenkins -> System -> Gitee Configuration -> Gitee connections 2、在 Connection name 中输入 Gitee 或者你想要的名字 3、Gitee host URL 中…

[STM32] EXTI 外部中断 (三)

文章目录 1.中断1.1 中断系统1.2 中断流程 2.STM32 中断2.1 EXTI&#xff08;外部中断&#xff09;2.2 EXTI 的基本结构2.3 AFIO 复用IO口2.4 EXTI 的框图 3.NVIC 基本结构3.1 NVIC 优先级分组 4.配置 EXTI4.1 AFIO 库函数4.2 EXTI 库函数4.3 NVIC 库函数4.4 配置EXTI 的步骤4.…

浅谈人工智能之DB-GPT(番外篇)Chat Excel功能示例

浅谈人工智能之DB-GPT&#xff08;番外篇&#xff09;Chat Excel功能示例 当我们安装完成DB-GTP以后&#xff0c;我们就可以对该功能进行使用&#xff0c;本文以Chat Excel功能未示例&#xff0c;介绍DB-GPT的强大功能。 Excel准备 首先我们准备一份Excel&#xff0c;该Exce…