在react中使用redux react-redux的使用demo
前言:
redux是一种状态管理工具,可以存储和操作一些全局或者很多组件需要使用的公共数据。
平心而论,redux的使用对于新上手来说不太友好,多个依赖包的,多种api的结合使用,相对来说比做同样一件事的vuex用起来比较麻烦.不过,熟能生巧,用多了也就习惯了,下面是个人的一个demo,是自己根据尚硅谷张天禹react教程学习的,然后写的demo.
这个demo是一个实用版本的demo,而不是深入研究redux本身的各种api操作
思路和准备:
需要的依赖包:
redux : 状态管理的核心插件(不仅仅是在react中能用,也可以在vue中用,但很显然,vue不需要 !--)
react-redux : 专门让redux和react之间对接的一个插件,让redux写起来没有那么的麻烦,(相对没有)
redux-devtools-extension : 调试工具,类似于vue-devtools,方便调试和查看,(当然了,本人是console.log党,用得少,配置上就行了)
redux-thunk: 可以让redux的值进行异步的修改,比较重要,能节省不少东西
思路:
首先,先要创建一个store,store是每个组件访问的核心,就像淘宝网站一样.
然后每个网站里面都有自己的商店,不同的商店对应不同的商品和购买方式,所以你就需要针对具体的数据类型,配置具体操作他的方法.
然后每个组件就像消费者一样,可以直接访问淘宝网站和站内所有的店铺,并且可以选取你希望他方式购买他,并且你的消费对其他客户也会造成影响,比如这件商品只剩一件了,你买了,其他用户就没货了,这也就是全局数据状态共享的意义.
ok了.学会了这些,那就直接展示代码了,感觉条例还是比较清晰的.
文件结构
|-- src(业务文件夹) ---------------互联网世界
|--pages(普通组件文件夹) --------------电商领域
|--index.jsx(demo父组件) --------------消费者集合
|--demo1.jsx(子组件1) --------------消费者1
|--demo2.jsx(子组件2) --------------消费者2
|--redux(redux文件夹)
|--actions(修改demo1数据状态的操作函数集合) ------------消费者购物方式集合
|--demo1Actions.js(demo1数据操作方法) -------------京东支付,选择加急,使用京豆
|--demo2Actions.js(demo2数据操作方法) -------------微信支付,不着急,坐等快递
|--reducers(全局状态初始化和操作分发的集合)
|--demo1.js(demo1的数据) -------------网店1
|--demo2.js(demo2的数据) -------------网店2
|--index.js(全局数据集合) --------------网店集合
|--store.js(全局数据的载体) ---------------电商网站
|--App.jsx(根组件)
|--main.jsx(项目入口组件) ---------------互联网
大概就是这么一个比喻,希望看客老爷们能理解我的这种比喻
某位大佬创建了一个电商网站,叫做四道(store).store里面可以创建很多网店,这些网店叫做瑞丢瑟斯(reducers).现在两个消费者,戴某1和戴某2,有两个店铺叫做demo1和demo2.
戴某1看上了demo1店铺的一件商品,情侣表,这个商品只有2件了,然后demo1就买了他,他将这个商品的接收地址分别发给了他自己和他对象那里,这个怎么买是他自己决定的,这个操作就是艾克神(action).因为戴某1买了这两件件商品,demo1店铺里面就没有这两件商品了.等到戴某2也想买这件商品的时候,发现这件商品已经空了.所以,店铺练得商品就是全局的数据or状态.
ok了,上具体代码:
代码
redux/store.js
// store构建方法
import {legacy_createStore,applyMiddleware} from 'redux'// 支持异步
import thunk from 'redux-thunk'// 开发工具
import {composeWithDevTools} from 'redux-devtools-extension'// 所有的reducers
import reducer from './reducers'// 将这些方法和参数组合,形成一个全局的store,store也是redux的核心
export default legacy_createStore(reducer,composeWithDevTools(applyMiddleware(thunk)))
main.js
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import 'reset-css'
import './index.css'
import store from './redux/store.js'
import {Provider} from 'react-redux'ReactDOM.createRoot(document.getElementById('root')).render(// <React.StrictMode><Provider store={store}><App /></Provider>// </React.StrictMode>,
)
redux/reducers/index.js
import {combineReducers} from 'redux'
import demo1 from './demo1'
import demo2 from './demo2'//将会在store上暴露的模块
export default combineReducers({demo1,demo2
})
redux/reducers/demo1.js
const initValue = 0
export default function demo1(value = initValue,action){console.log(action,'点击了')const {type,data} = actionswitch(type){case 'add':return value+data;case 'delete':return value-data;default:return value}
}
redux/reducers/demo2.js
//初始化的值
const initValue = {name:'王惊涛',age:27
}export default function demo2(value=initValue,action){
const {type,data} = action
switch(type){case 'change':return datadefault:return value
}
}
redux/actions/demo1Actions.js
export const addAction = data => ({type:'add',data})
export const deleteAction = data => ({type:'delete',data})
export const asyncAddAction = (data,time) => {return (dispatch)=>{setTimeout(()=>{dispatch(addAction(data))},time)}
}
redux/actions/demo2Actions.js
export const changeData = data => ({type:'change',data})
src/pages/index.jsx
import React, { Component } from 'react'
import withRouter from '../../utils/withRouter'
import Demo1 from './demo1'
import Demo2 from './demo2'
export default withRouter(class index extends Component {render() {return (<div><Demo1></Demo1><hr /><Demo2></Demo2></div>)}
})
src/pages/demo1.jsx
import React, { Component } from 'react'
import withRouter from '../../utils/withRouter'
import {connect} from 'react-redux'
import {addAction,deleteAction} from '../../redux/actions/demo1Actions'
import {Button} from 'antd'
const Demo1 = withRouter(class index extends Component {addValue = ()=>{this.props.addAction(1)}deleteValue = ()=>{this.props.deleteAction(1)}render() {console.log(this.props,'this.props---')return (<div><h4>demo1页面</h4><p>原始操作值:{this.props.demo1}</p><Button onClick={this.addValue}>增加1</Button><Button onClick={this.deleteValue}>减少1</Button><br /><p>demo2里面的内容:---- 姓名:{this.props.demo2.name} 年龄:{this.props.demo2.age}</p></div>)}
})export default connect(state =>({demo1:state.demo1,demo2:state.demo2}),{addAction,deleteAction}
)(Demo1)
src/pages/demo2.jsx
import React, { Component } from 'react'
import withRouter from '../../utils/withRouter'
import { connect } from 'react-redux'
import {changeData} from '../../redux/actions/demo2Actions'
import {addAction} from '../../redux/actions/demo1Actions'
import {Input,Button} from 'antd'
const Demo2 = withRouter( class index extends Component {state = {data:null}InputStype = {width:'400px'}componentDidMount(){console.log(this.props,'demo2中的props值')this.setState({data:this.props.demo2},()=>{console.log(this.props,'this.props---demo2???')})}changeData = ()=>{this.props.changeData({name:'马师',age:28})}addHandler = ()=>{this.props.addAction(1)}render() {return (<div><h4>demo2页面</h4><Button onClick={this.changeData}>修改值</Button><Button onClick={this.addHandler}>增加值</Button><p>姓名:{this.props.demo2.name}</p><p>年龄:{this.props.demo2.age}</p><br /><p>demo1里面的值:{this.props.demo1}</p></div>)}
})export default connect(state=>({demo1:state.demo1,demo2:state.demo2}),{changeData,addAction}
)(Demo2)
withRouter.jsx
import {useLocation,useNavigate,useParams,} from "react-router-dom";function withRouter(Component) {function ComponentWithRouterProp(props) {let location = useLocation();let navigate = useNavigate();let params = useParams();return (<Component{...props}router={{ location, navigate, params }}/>);}return ComponentWithRouterProp;}export default withRouter
感觉有用的就给个赞吧,谢啦!
相关文章:
在react中使用redux react-redux的使用demo
前言: redux是一种状态管理工具,可以存储和操作一些全局或者很多组件需要使用的公共数据。 平心而论,redux的使用对于新上手来说不太友好,多个依赖包的,多种api的结合使用,相对来说比做同样一件事的vuex用起来比较麻烦.不过,熟能生巧,用多了也就习惯了,下面是个人的一个demo,…...
Flutter 06 动画
一、动画基本原理以及Flutter动画简介 1、动画原理: 在任何系统的Ul框架中,动画实现的原理都是相同的,即:在一段时间内,快速地多次改变Ul外观;由于人眼会产生视觉暂留,所以最终看到的就是一个…...
优化改进YOLOv5算法之添加MS-Block模块,有效提升目标检测效果(超详细)
目录 前言 1 MS-Block原理 1.1 Multi-Scale Building Block Design 1.2 Heterogeneous Kernel Selection Protocol 2 YOLOv5算法中加入MS-Block...
【论文阅读】Iterative Poisson Surface Reconstruction (iPSR) for Unoriented Points
文章目录 声明作者列表核心思想归纳算法流程机器翻译声明 本帖更新中如有问题,望批评指正!如果有人觉得帖子质量差,希望在评论中给出建议,谢谢!作者列表 FEI HOU(侯飞)、CHIYU WANG、WENCHENG WANG:中国科学院大学 HONG QIN CHEN QIAN、YING HE 核心思想归纳 当一条从…...
通过akshare获取股票分钟数据
参考:https://blog.csdn.net/qnloft/article/details/131218295 import akshare as ak 个股的 df ak.stock_zh_a_hist_min_em(symbol“000001”, start_date“2023-11-03 09:30:00”, end_date“2023-11-03 15:00:00”, period‘1’, adjust‘’) print(df) date_info df[‘…...
【论文阅读笔记】Traj-MAE: Masked Autoencoders for Trajectory Prediction
Abstract 通过预测可能的危险,轨迹预测一直是构建可靠的自动驾驶系统的关键任务。一个关键问题是在不发生碰撞的情况下生成一致的轨迹预测。为了克服这一挑战,我们提出了一种有效的用于轨迹预测的掩蔽自编码器(Traj-MAE),它能更好地代表驾驶…...
MySQL - Zero date value prohibited
问题: timestamp字段报Caused by: com.mysql.cj.exceptions.DataReadException: Zero date value prohibited 原因: timestamp字段存入了0值, 超出了最小值1900-01-01 00:00:00, 转Java对象的时候报错 解决: 1.修复或删除原数据 2. mysqlurl 中添加zeroDateTimeBehaviorconve…...
设计模式——迭代器模式(Iterator Pattern)+ Spring相关源码
文章目录 一、迭代器模式二、例子2.1 菜鸟例子2.1.1 定义迭代器接口2.1.2 定义迭代对象接口——用于返回一个迭代器2.1.3 实现 迭代对象 和 迭代器2.1.4 使用 2.2 JDK源码——ArrayList2.3 Spring源码——DefaultListableBeanFactory 三、其他设计模式 一、迭代器模式 类型&am…...
【word技巧】ABCD选项如何对齐?
使用word文件制作试卷,如何将ABCD选项全部设置对齐?除了一直按空格或者Tab键以外,还有其他方法吗?今天分享如何将ABCD选项对齐。 首先,我们打开【替换和查找】,在查找内容输入空格,然后点击全部…...
如何在uni-app小程序端实现长按复制功能
在开发小程序应用中,常常需要使用到长按复制功能。本文将介绍如何在uni-app小程序端实现长按复制功能。 uni-app是一个跨平台的开发框架,可以基于vue.js语法开发小程序、H5、APP等多个平台的应用。uni-app提供了一些内置组件和API,可以方便地…...
基于springboot实现在线考试平台项目【项目源码+论文说明】计算机毕业设计
基于springboot实现在线考试演示 摘要 网络的广泛应用给生活带来了十分的便利。所以把在线考试管理与现在网络相结合,利用java技术建设在线考试系统,实现在线考试的信息化。则对于进一步提高在线考试管理发展,丰富在线考试管理经验能起到不少…...
【移远QuecPython】EC800M物联网开发板的内置GNSS定位获取(北斗、GPS和GNSS)
【移远QuecPython】EC800M物联网开发板的内置GNSS定位获取(北斗、GPS和GNSS) 测试视频(其中的恶性BUG会在下一篇文章阐述): 【移远QuecPython】EC800M物联网开发板的内置GNSS定位的恶性BUG(目前没有完全的…...
软件设计师2016下半年下午——KMP算法和装饰设计模式
下面是提供的代码的逐行注释,以及对next数组在KMP算法中的作用的解释: #include <iostream> #include <vector> using namespace std;void buildNextArray(const char* pattern, vector<int>& next) {int m strlen(pattern); …...
Android Studio run main()方法报错
在studio中想要测试某个功能直接执行main()方法报错如下: * What went wrong: A problem occurred configuring project :app. > Could not create task :app: **** .main().> SourceSet with name main not found.解决方案: 执行run ** main() w…...
CM3D2 汉化杂记
老物难找资源,于是尝试自己汉化,皆源于有一个好的汉化插件。 资源:LMMT 工具:CM3D2.SubtitleDumper.exe,有道翻译(可以翻译文档),Libreoffice(文档、表格) cmd(资源管理器的结果可以拖进去&…...
分类预测 | Matlab实现SMA-KELM黏菌优化算法优化核极限学习机分类预测
分类预测 | Matlab实现SMA-KELM黏菌优化算法优化核极限学习机分类预测 目录 分类预测 | Matlab实现SMA-KELM黏菌优化算法优化核极限学习机分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.MATLAB实现SMA-KELM黏菌优化算法优化核极限学习机分类预测(完整源码和数…...
linux的环境安装以及部署前后端分离后台接口
⭐⭐ linux专栏:linux专栏 ⭐⭐ 个人主页:个人主页 目录 一.linux安装环境 1.1 jdk和tomcat的安装配置 1.1.1 解压jdk和tomcat的安装包 解压jdk安装包 解压tomcat安装包 1.2 jdk环境变量配置 1.3 tomcat启动 1.4 MySQL的安装 二.部署前后端分离…...
解决mysql数据库root用户看不到库
第一种方式: 1.首先停止MySQL服务:service mysqld stop 2.加参数启动mysql:/usr/bin/mysqld_safe --skip-grant-tables & 然后就可以无任何限制的访问mysql了 3.root用户登陆系统:mysql -u root -p mysql 4.切换数据库&#…...
【LeetCode】117. 填充每个节点的下一个右侧节点指针 II
117. 填充每个节点的下一个右侧节点指针 II 难度:中等 题目 给定一个二叉树: struct Node {int val;Node *left;Node *right;Node *next; }填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,…...
《研发效能(DevOps)工程师》课程简介(三)丨IDCF
在研发效能领域中,【开发与交付】的学习重点在于掌握高效的开发工具和框架,了解敏捷开发方法,掌握持续集成与持续交付技术,以及如何保证应用程序的安全性和合规性等方面。 由国家工业和信息化部教育与考试中心颁发的职业技术证书…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
