react之react-redux的介绍、基本使用、获取状态、分发动作、数据流、reducer的分离与合并等

news2024/11/15 17:53:29

react之react-redux的介绍、基本使用、获取状态、分发动作、数据流、reducer的分离与合并等

  • 一、react-redux介绍
  • 二、React-Redux-基本使用
  • 三、获取状态useSelector
  • 四、分发动作useDispatch
  • 五、 Redux 数据流
  • 六、代码结构
  • 七、ActionType的使用
  • 八、Reducer的分离与合并
  • 九、购物挣钱案例

一、react-redux介绍

  • 官网地址
  • React 和 Redux 是两个独立的库,两者之间职责独立。因此,为了实现在 React 中使用 Redux 进行状态管理 ,就需要一种机制,将这两个独立的库关联在一起。这时候就用到 React-Redux 这个绑定库了
  • 作用:为 React 接入 Redux,实现在 React 中使用 Redux 进行状态管理。
  • react-redux 库是 Redux 官方提供的 React 绑定库。

在这里插入图片描述

二、React-Redux-基本使用

  • react-redux 的使用分为两大步:1 全局配置(只需要配置一次) 2 组件接入(获取状态或修改状态)
  • 全局配置
    • 1.安装 react-redux:npm i react-redux
    • 2.从 react-redux 中导入 Provider 组件
    • 3.导入创建好的 redux 仓库
    • 4.使用 Provider 包裹整个应用
    • 5.将导入的 store 设置为 Provider 的 store 属性值

index.js 核心代码

// 导入 Provider 组件
import { Provider } from 'react-redux'
// 导入创建好的 store
import store from './store'

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.querySelector('#root')
)

三、获取状态useSelector

  • useSelector:获取 Redux 提供的状态数据

  • 参数:selector 函数,用于从 Redux 状态中筛选出需要的状态数据并返回

  • 返回值:筛选出的状态

    import { useSelector } from 'react-redux'

    // 计数器案例中,Redux 中的状态是数值,所以,可以直接返回 state 本身
    const count = useSelector(state => state)

    // 比如,Redux 中的状态是个对象,就可以:
    const list = useSelector(state => state.list)

App.js中核心代码

import { useSelector } from 'react-redux'

const App = () => {
  const count = useSelector(state => state)
  
  return (
  	<div>
    	<h1>计数器:{count}</h1>
      <button>数值增加</button>
			<button>数值减少</button>
    </div>
  )
}

四、分发动作useDispatch

  • useDispatch:拿到 dispatch 函数,分发 action,修改 redux 中的状态数据
  • 语法
import { useDispatch } from 'react-redux'

// 调用 useDispatch hook,拿到 dispatch 函数
const dispatch = useDispatch()

// 调用 dispatch 传入 action,来分发动作
dispatch( action )

App.js 中核心代码

import { useDispatch } from 'react-redux'

const App = () => {
  const dispatch = useDispatch()
  
  return (
  	<div>
    	<h1>计数器:{count}</h1>
      {/* 调用 dispatch 分发 action */}
      <button onClick={() => dispatch(increment(2))}>数值增加</button>
			<button onClick={() => dispatch(decrement(5))}>数值减少</button>
    </div>
  )
}

五、 Redux 数据流

在这里插入图片描述

  • 任何一个组件都可以直接接入 Redux,也就是可以直接:1 修改 Redux 状态 2 接收 Redux 状态
  • 并且,只要 Redux 中的状态改变了,所有接收该状态的组件都会收到通知,也就是可以获取到最新的 Redux 状态
  • 跨组件可直接通讯

六、代码结构

  • 在使用 Redux 进行项目开发时,不会将 action/reducer/store 都放在同一个文件中,而是会进行拆分
  • 可以按照以下结构,来组织 Redux 的代码:
/store        --- 在 src 目录中创建,用于存放 Redux 相关的代码
  /actions.js    --- 存放所有的 action
  /reducers.js   --- 存放所有的 reducer
  index.js    --- redux 的入口文件,用来创建 store

示例actions.js

export const AddMoney = (money) => ({ type: 'add_money', money })
export const SubMoney = (money) => ({ type: 'sub_money', money })

示例reducers.js

export default function reducer(state = 1000, action) {
  if (action.type === 'add_money') {
    return state + action.money
  }
  if (action.type === 'sub_money') {
    return state - action.money
  }
  return state
}

示例index.js

//createStore 方法已被启用
import { legacy_createStore as createStore } from 'redux'

import reducer from './reducer'
console.log('reducer', reducer)
const store = createStore(reducer)

export default store

七、ActionType的使用

  • Action Type 指的是:action 对象中 type 属性的值
  • Redux 项目中会多次使用 action type,比如,action 对象、reducer 函数、dispatch(action) 等
  • 目标:集中处理 action type,保持项目中 action type 的一致性
  • action type 的值采用:'domain/action'(功能/动作)形式,进行分类处理,比如,
    • 计数器:'counter/increment' 表示 Counter 功能中的 increment 动作
    • 登录:'login/getCode' 表示登录获取验证码的动作
    • 个人资料:'profile/get' 表示获取个人资料

步骤

  • 1.在 store 目录中创建 actionTypes 目录或者 constants 目录,集中处理
  • 2.创建常量来存储 action type,并导出
  • 3.将项目中用到 action type 的地方替换为这些常量,从而保持项目中 action type 的一致性

核心代码

// actionTypes 或 constants 目录:

const increment = 'counter/increment'
const decrement = 'counter/decrement'

export { increment, decrement }

// --

// 使用:

// actions/index.js
import * as types from '../acitonTypes'
const increment = payload => ({ type: types.increment, payload })
const decrement = payload => ({ type: types.decrement, payload })

// reducers/index.js
import * as types from '../acitonTypes'
const reducer = (state, action) => {
  switch (action.type) {
    case types.increment:
      return state + 1
    case types.decrement:
      return state - action.payload
    default:
      return state
  }
}
  • 注:额外添加 Action Type 会让项目结构变复杂,此操作可省略。但,domain/action 命名方式强烈推荐!

八、Reducer的分离与合并

  • 随着项目功能变得越来越复杂,需要 Redux 管理的状态也会越来越多
  • 此时,有两种方式来处理状态的更新
    • 1.使用一个 reducer:处理项目中所有状态的更新
    • 2.用多个 reducer:按照项目功能划分,每个功能使用一个 reducer 来处理该功能的状态更新
  • 推荐:使用多个 reducer(第二种方案),每个 reducer 处理的状态更单一,职责更明确
  • 此时,项目中会有多个 reducer,但是 store 只能接收一个 reducer,因此,需要将多个 reducer 合并为一根 reducer,才能传递给 store
  • 合并方式:使用 Redux 中的 combineReducers 函数
  • 注意:合并后,Redux 的状态会变为一个对象,对象的结构与 combineReducers 函数的参数结构相同

核心代码

import { combineReducers } from 'redux'

// 计数器案例,状态默认值为:0
const aReducer = (state = 0, action) => {}
// Todos 案例,状态默认值为:[]
const bReducer = (state = [], action) => {}

// 合并多个 reducer 为一个 根reducer
const rootReducer = combineReducers({
  a: aReducer,
  b: bReducer
})

// 创建 store 时,传入 根reducer
const store = createStore(rootReducer)

// 此时,合并后的 redux 状态: { a: 0, b: [] }

九、购物挣钱案例

  • 基本结构 跟组件下包含两个子组件
  • 实现功能 点击子组件对应的按钮 实现根组件 兄弟组件资金的更改
  • 需安装react-redux 和 redux
    在这里插入图片描述

代码基本目录

在这里插入图片描述

index.js 代码

import ReactDom from 'react-dom/client'
import App from './App'
//引入Provider
import { Provider } from 'react-redux'

//引入store
import store from './store/index'

ReactDom.createRoot(document.querySelector('#root')).render(
  <Provider store={store}>
    <App></App>
  </Provider>
)

App.js代码

import Women from './components/women'
import Man from './components/man'
//引入useSelector 
import { useSelector } from 'react-redux'

export default function App() {

  const money = useSelector((state) => {
    return state.money
  })
  
  return (
    <div>
      <h1>我是根组件</h1>
      <div>资金:{money}</div>
      <Women></Women>
      <Man></Man>
    </div>
  )
}

women组件

//引入  useSelector, useDispatch
import { useSelector, useDispatch } from 'react-redux'

//引入 action下的SubMoney 
import { SubMoney } from '../store/action'

export default function Man() {

  const money = useSelector((state) => state.money)
  const dispath = useDispatch()
  
  return (
    <div>
      <h3>女人组件</h3>
      <div>金钱:{money}</div>
      <button
        onClick={() => {
          dispath(SubMoney(500))
        }}
      >
        买包-500
      </button>
    </div>
  )
}

men组件

//引入  useSelector, useDispatch
import { useSelector, useDispatch } from 'react-redux'

//引入action下的 AddMoney 
import { AddMoney } from '../store/action'

export default function Women() {
  const money = useSelector((state) => state.money)
  const dispath = useDispatch()
  return (
    <div>
      <h3>男人组件</h3>
      <div>金钱:{money}</div>
      <button onClick={() => dispath(AddMoney(10))}>搬砖 + 10</button>
      <button onClick={() => dispath(AddMoney(10000))}>卖肾 + 10000</button>
    </div>
  )
}

store文件下的action.js 代码

//按需导出
export const AddMoney = (money) => ({ type: 'add_money', money })
export const SubMoney = (money) => ({ type: 'sub_money', money })

store文件下的reducer.js 代码

//引入 combineReducers
import { combineReducers } from 'redux'

//user模块
function user(state = { name: '张三', age: '20岁' }, action) {
  return state
}
//money 模块
function money(state = 1000, action) {
  if (action.type === 'add_money') {
    return state + action.money
  }
  if (action.type === 'sub_money') {
    return state - action.money
  }
  return state
}

//模块化
const rootReducer = combineReducers({
  user,
  money,
})

console.log('导出', rootReducer)
export default rootReducer


store文件下的index.js 代码

//createStore 方法已被启用
import { legacy_createStore as createStore } from 'redux'

import reducer from './reducer'
console.log('reducer', reducer)
const store = createStore(reducer)

export default store

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

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

相关文章

python:tkinter + cef 模仿 mdict 界面

cefpython3 其上游是C开发的CEF&#xff08;基于webkit、V8&#xff09;&#xff0c; CEF 即 (Chromium Embedder Framework)&#xff0c; 是基于Google Chromium项目的开源 Web browser控件(WebView)。 可查看github文档&#xff1a;cefpython api pip install cefpython3 c…

信号灯集和共享内存的综合应用小例子

要求&#xff1a;使用信号灯集和共享内存实现&#xff1a;一个进程对共享内存存放数据"Nice to meet you"循环倒置&#xff0c;一个进程循环输出共享内存的内容&#xff0c;要确保倒置一次打印一次。 分析&#xff1a;这两个进程可以写成两个源文件&#xff0c;一个…

回归预测 | MATLAB实现SSA-SVM麻雀搜索算法优化支持向量机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现SSA-SVM麻雀搜索算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现SSA-SVM麻雀搜索算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09;效果一览基…

VCRUNTIME140_1.dll丢失是怎么回事?三个解决方法分享

最近打开软件或者游戏的时出现了以下问题一开始以为是自己手残又误删了什么&#xff0c;重新安装了两次也没有解决&#xff0c;看网上有许多朋友安装其他软件时会出现缺少VCRUNTIME140.dll&#xff0c;其实VCRUNTIME140_1.dll是微软Visual C Redistributable安装包中的一个动态…

AgentBench——AI智能体基准测试和排行榜

如果您有兴趣了解有关如何对AI大型语言模型或LLM进行基准测试的更多信息,那么一种新的基准测试工具Agent Bench已成为游戏规则的改变者。这个创新工具经过精心设计,将大型语言模型列为代理,对其性能进行全面评估。该工具的首次亮相已经在AI社区掀起了波澜,揭示了ChatGPT-4目…

音视频 FFmpeg音视频处理流程

ffmpeg -i test_1920x1080.mp4 -acodec copy -vcodec libx264 -s 1280x720 test_1280x720.flv推荐一个零声学院项目课&#xff0c;个人觉得老师讲得不错&#xff0c;分享给大家&#xff1a; 零声白金学习卡&#xff08;含基础架构/高性能存储/golang云原生/音视频/Linux内核&am…

修复由于找不到vcruntime140.dll,无法继续执行代码的问题方法

提示“由于找不到 VCRUNTIME140.dll&#xff0c;无法继续执行代码。重新安装程序可能会解决此问题。”&#xff0c;这一般是什么原因导致了这个问题&#xff0c;我们要如何解决&#xff1f; 下面分享一下由于找不到vcruntime140.dll无法继续执行代码的解决方法。 解决方法&…

【C++】C++入门基础:引用详解

本篇继续分享关于C入门的相关知识&#xff0c;有关命名空间、缺省参数和函数重载的部分欢迎阅读我的上一篇文章【C】C入门基础详解&#xff08;1&#xff09;_王笃笃的博客-CSDN博客 继续我们的学习 引用 在C语言中我们接触过指针&#xff0c;很多人都或多或少为他感到头痛过…

开源后台管理系统Geekplus Admin

本系统采用前后端分离开发模式&#xff0c;后端采用springboot开发技术栈&#xff0c;mybatis持久层框架&#xff0c;redis缓存&#xff0c;shiro认证授权框架&#xff0c;freemarker模版在线生成代码&#xff0c;websocket消息推送等&#xff0c;后台管理包含用户管理&#xf…

1122.数组的相对排序

目录 一、题目 二、分析代码 一、题目 二、分析代码 核心计数排序&#xff01;&#xff01;&#xff01; class Solution { public: vector<int> relativeSortArray(vector<int>& arr1, vector<int>& arr2) {int n arr1.size();int arr1_Max I…

C++ string类详解

⭐️ string string 是表示字符串的字符串类&#xff0c;该类的接口与常规容器的接口基本一致&#xff0c;还有一些额外的操作 string 的常规操作&#xff0c;在使用 string 类时&#xff0c;需要使用 #include <string> 以及 using namespace std;。 ✨ 帮助文档&…

USB隔离器电路分析,SA8338矽塔sytatek电机驱动,源特科技VPS8701,开关电源,电源 大师

一、 USB隔离器电路分析 进行usb隔离可以使用USB隔离模块 ADUM3160 ADUM4160 注意&#xff1a;B0505S 最大带载0.16A&#xff0c;副边需要带载能力需要改变方案 比如移动硬盘至少需要0.5A 用充电宝、18650、设计5V1A输出电源 二、 1A隔离电压方案

【蓝桥杯】[递归]母牛的故事

原题链接&#xff1a;https://www.dotcpp.com/oj/problem1004.html 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 我们列一个年份和母牛数量的表格&#xff1a; 通过观察&#xff0c;找规律&#xff0c;我们发现&#xff1a; 当年份小于等于4时&…

Linux环境下python连接Oracle教程

下载Oracle client需要的 安装包 rpm包下载地址&#xff1a;Oracle官方下载地址 选择系统版本 选择Oracle版本 下载3个rpm安装包 oracle-instantclient12.2-basic-12.2.0.1.0-1.i386.rpm oracle-instantclient12.2-devel-12.2.0.1.0-1.i386.rpm oracle-instantclient12.2-sq…

算法通关村第八关——轻松搞定二叉树的深度和高度问题

1.基础知识 二叉树节点的高度&#xff1a;指从当前节点到叶子节点的最长简单路径边的条数 二叉树节点的深度&#xff1a;指从根节点到当前节点的最长简单路径边的条数 二叉树的深度和高度问题&#xff0c;递归思想的运用很是普遍&#xff0c;有的问题层序遍历也可以解决。 2.最…

PyTorch Lightning:通过分布式训练扩展深度学习工作流

一、介绍 欢迎来到我们关于 PyTorch Lightning 系列的第二篇文章&#xff01;在上一篇文章中&#xff0c;我们向您介绍了 PyTorch Lightning&#xff0c;并探讨了它在简化深度学习模型开发方面的主要功能和优势。我们了解了 PyTorch Lightning 如何为组织和构建 PyTorch 代码提…

3种获取OpenStreetMap数据的方法【OSM】

OpenStreetMap 是每个人都可以编辑的世界地图。 这意味着你可以纠正错误、添加新地点&#xff0c;甚至自己为地图做出贡献&#xff01; 这是一个社区驱动的项目&#xff0c;拥有数百万注册用户。 这是一个社区驱动的项目&#xff0c;旨在在开放许可下向每个人提供所有地理数据。…

基于YOLOv8模型的奶牛目标检测系统(PyTorch+Pyside6+YOLOv8模型)

摘要&#xff1a;基于YOLOv8模型的奶牛目标检测系统可用于日常生活中检测与定位奶牛目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的目标检测&#xff0c;另外本系统还支持图片、视频等格式的结果可视化与结果导出。本系统采用YOLOv8目标检测算法训练数据集…

【小梦C嘎嘎——启航篇】vector 以及日常使用的接口介绍

【小梦C嘎嘎——启航篇】vector 日常使用的接口介绍&#x1f60e; 前言&#x1f64c;vector 是什么&#xff1f;vector 比较常使用的接口 总结撒花&#x1f49e; &#x1f60e;博客昵称&#xff1a;博客小梦 &#x1f60a;最喜欢的座右铭&#xff1a;全神贯注的上吧&#xff01…

Parking Steps

上面是老师傅说的停车步骤&#xff0c;说这样不会伤变速箱。 平时就是&#xff0c;脚踩刹车&#xff0c;直接从D档撸到P档&#xff0c;拉手刹&#xff0c;哈哈。 你的停车步骤是啥。。