react-8 Redux 状态管理 - 持久化存储 => 进阶:React-Redux()和模块化

news2024/11/20 0:42:18

1.redux

redux是独立于react的库,是js状态管理库,提供可预测的状态管理。Vue也可用,但是和react比较搭配 。

2. 什么时候用 redux?

解决:任意:多组件共享状态,

解决:任意:两个组件共享数据

3. 三大原则(API) :::背

安装:

//最新版是配合函数式,我们这是class类组件式:所以装4
npm i redux@4

单一数据源store是共享的,但是是只读的,获取store,store.getState()。

单一数据源, 整个应用的 state 被储存一一个 store 任何组件都可以访问到状态,更容易地将状态持久化到本地存储或远程服务器中。

//单一数据源store数据仓库,只读的
console.log( store.getState() ) 

修改需要 store.dispatch() 触发action,调用纯函数执行修改

修改后需要:监听store中数据的变化, store.subscribe()

State 是只读的, 唯一改变 state 的方法就是触发(派发) actionaction 是一个用于描述已发生事件的普通对象

//State 只读的,想修改需要触发action
store.dispatch({    type: 'DELETE_TODO',    index: 1 
}) 

//监听store中数据的变化
store.subscribe()

store.dispatch() 触发action,调用纯函数reducer 执行修改

action触发后:需要使用纯函数来执行修改, 为了描述 触发 action 后如何改变 state tree ,你需要编写reducer:reducer 只做一件事情,通过之前的 state 和当前的 action 计算得出新的 state ,因此 reducer 必须是一个纯函数(reducer 不应该写有副作用的代码,比如定时器,ajax 请求).

4. 使用 Redux :

react中没有响应式数据,要自己触发

可以多组件: 触发action 传值,会执行reducer.ts

多组件都可修改,但是值不实时更新,这里都要监听解决:让组件更新,可以获得实时数据

但是监听可能会导致内存泄漏:组件不见了,还在执行,内存泄漏了:取消监听解决

配置:实例化store

store下index.ts

//AAA 原始
//导入createStore
import { createStore } from 'redux'

//导入reducer(纯函数)
import reducer from './reducer'

//实例化store并导出
export default createStore(reducer)

store下reducer.ts :执行reducer.ts,记得返回新值,共享数据

1.   不要直接修改 state 我们使用  JSON.parse(JSON.stringfy()) { ...state, ...newState } 新建一个 state 副本(拷贝)。不能这样使用 Object.assign(state, { text: action }),因为它会改变第一个参数的值。你必须把第一个参数设置为空对象。你也可以使用 { ...state, ...newState } 达到相同的目的。

2.   在default 情况下返回旧的 state。遇到未知的 action 时,一定要返回旧的 state

var initialState = {
    count: 0
}
var reducer = (state = initialState, action: any) => {
    // 深拷贝state
    var newstate = JSON.parse(JSON.stringify(state))
    if (action.type == 'ADD') {
        newstate.count += action.payload;

        console.log(newstate);
        return newstate; //返回新的state
    } else if (action.type == "SUB") {
        newstate.count -= action.payload;
        
        console.log(newstate);
        return newstate; //返回新的state
    } else {
        return state //返回旧的state(之前的state)
    }
}

export default reducer;

使用:比如详情 和购物车都可以操作count

组件1,详情。组件2,购物车(使用是一样的)

subscribe监听触发实时更新,但是会内存泄漏:解决内存泄漏:组件都需要 取消监听

import React, { Component } from 'react';
import store from '../../../store'
//store.getState() //获取store中的数据
//store.dispatch() //触发action修改store中的数据 
//store.subscribe() //监听store中的数据的变化 

//store.getState() 在执行时 默认会自动触发store中的reducer纯函数的执行( reducer纯函数内部务必返回state )
//store.dispatch() 在执行时 会自动触发store中的reducer纯函数的执行( reducer纯函数内部会执行最终的修改, 返回修改后的新state )
class Cate extends Component {
    unsubscribe:any = 100;
    componentDidMount() {
        //监听store中的数据的变化(会造成内存泄漏),记得要取消监听
        this.unsubscribe = store.subscribe(()=>{
            this.setState({});
            console.log('Cate 监听回调');
        })
    }
    componentWillUnmount() {
        //取消监听
        this.unsubscribe();
    }
    handleClick(){
        //触发action, 修改redux中的数据
        store.dispatch( { type:'ADD', payload:1 } )
    }
    render() {
        console.log( store.getState() );
        return (
            <div className='cate'>
                <h3>详情页面 - {store.getState().count}</h3>
                <button onClick={()=>{ this.handleClick() }}>添加</button>
            </div>
        );
    }
}

export default Cate;

5. 数据流 :::背

通过dispach触发action

store调用reducer纯函数

纯函数返回新的state保存在store中

6. react-redux 作用:可以不用导入store,看不见store,也不用subscribe监听了,也没有内存泄漏了,

但是connet结构必须写

安装:

npm i react-redux

根组件上:Provider,store

 store下index.ts


// BBB 添加了:::npm i react-redux
// 导入createStore
import { createStore } from 'redux'

// 导入reducer(纯函数):::那边直接导出了,所以对象解构接收
import {reducer} from './reducer'

// 实例化store并导出
export default createStore(reducer)

reducer.ts

高阶函数content直接导出:

作用:

content 第一个函数:将属性写入到组件的props中。第二个函数:将方法写入到组件的props中。

content 会让当前座机和store联系起来。

content 会监听store的变化,一旦store中的数据发生改变,当前组件会自动更新  

 content结构

直接调用了 ,这点props记得写下ts

7. 代码模块化

 reducer:combinReducers可以合并reducer

 模块

模块

8. redux 中间件(插件)3个

redux-logger 中间件的使用日志打印

//redux-logger 是一个打印数据操作日志的中间件. 
npm i redux-logger 



//爆红的话
npm i --save-dev @types/redux-logger

  redux-thunk 中间件使用redux-thunk 允许在 action creator 中返回一个函数, 我们可以在该函数中实现异步操作. (redux只支持同步的action,这个解决)

// redux-thunk 允许在 action creator 中返回一个函数, 我们可以在该函数中实现异步操作. 
// eg:发请求
npm install redux-thunk

 redux-persist 插件的使用: 是一个能实现对 store 持久化的中间件.  持久化存储,自动触发一次。返回了新的newstate,报错。解决:返回旧的newstate

//redux-persist 是一个能实现对 store 持久化的中间件. 
npm i redux-persist 

store下index.ts配置

// store下index.ts配置


import { createStore,applyMiddleware } from 'redux'
import logger from 'redux-logger'
import thunk from 'redux-thunk'
// import m1 from './middlewares/m1'
// import m2 from './middlewares/m2'

import { persistStore, persistReducer } from 'redux-persist'
// import storage from 'redux-persist/lib/storage/session' // defaults to sessionStorage for web
import storage from 'redux-persist/lib/storage' // defaults to localStorage for web

//导入reducer
import {reducer} from './reducer'

//对reducer纯函数进行持久化处理
var persistedReducer = persistReducer({key:'redux',storage},reducer)

//实例化store实例   ,   applyMiddleware 负责应用中间到store( 每个中间件都会在reducer之前先执行 )
// export var store = createStore(persistedReducer,applyMiddleware(m1,m2,logger))
export var store = createStore(persistedReducer,applyMiddleware(logger,thunk))

//对store进行持久化处理
export var persistor = persistStore(store)

// reducer.ts 

// reducer.ts
// combinReducers 可以合并 reducer
import { combineReducers } from 'redux'
// 导入模块化的每个子reducer
import { tasklist_reducer } from './reducer/tasklist'
import { userinfo_reducer } from './reducer/userinfo'


// 合并每个子 reducer 成一个根reducer
export var reducer = combineReducers({
    tasklist: tasklist_reducer,
    userinfo: userinfo_reducer,
})

 //userinfo.ts文件

//userinfo.ts文件
// 子reducer纯函数,只管理一个{}
export var userinfo_reducer = function (state = {},action:any) {
    // 深拷贝
    var newstate = JSON.parse(JSON.stringify(state))
    if (action.type == 'SAVE_USERINFO') {
        newstate = action.payload;
        return newstate
    } else if(action.type == 'REMOVE_USERINFO'){
        newstate = {};
        return newstate
    } else {
        return state
    }
}

根目录index.ts

//根目录index.ts

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

//导入store和持久化处理后的store
import {store,persistor} from './store';

import {Provider} from 'react-redux'

//导入redux-persist提供的PersistGate组件
import { PersistGate } from 'redux-persist/integration/react'

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  // <React.StrictMode>
  // Provider 组件通过store属性将store传递给内层的每一个组件
  <Provider store={store}>
    <PersistGate loading={null} persistor={persistor}>
      <App />
    </PersistGate>
  </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();

 

其中:::redux-thunk 中间件使用redux-thunk 允许在 action creator 中返回一个函数, 我们可以在该函数中实现异步操作. (redux只支持同步的action,不支持函数式,redux-thunk 中间件 解决)

触发异步action。可以发请求了axios,存储数据了redux

项目中组件只负责构建,所以请求不要放在组件中,数据最好存起来,算是性能优化

: 了解:和think一样,但是区别太大,使用麻烦了点
npm i redux-sage

 9.自定义中间件 :::

 

自定义中间件和logger使用是一样的,自己定义不用下载了

//自定义中间件 m1
export default function({dispatch, getState}){
    return function( next ){
        return function (action){
            console.log('中间件1');
            return next(action)
        }
    }
}

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

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

相关文章

83.qt qml-初步学习2D粒子影响器(二)

由于QmlBook in chinese翻译过来的文字有些比较生疏难于理解,所以本章在它的基础上做些个人理解,建议学习的小伙伴最好配合QmlBook in chinese一起学习。 QML粒子所有类型: Qt Quick Particles QML Types | Qt Quick 6.5.0 Affector类型: Attractor QML Type | Qt Quick 6.5.…

TouchGFX界面开发 | TouchGFX软件安装

TouchGFX软件安装 TouchGFX和STemWin类似&#xff0c;都是一个GUI框架&#xff0c;可以方便的在STM32 Cortex-M4 以及更高级别的STM32芯片上创建GUI应用程序。 本文中的TouchGFX软件安装&#xff0c;是基于已经安装有STM32CubeMX Keil MDK-ARM开发环境的情况下进行的&#x…

CSS3 2D变换

CSS3 2D变换 位移&#xff1a; div {transform: translateX(30px); /*水平位移*/transform: translateY(30px); /*垂直位移*/transform: translate(30px, 30px); /*两个方向位移*/ }注意&#xff1a;位移的百分比是元素本身&#xff0c;不是父元素 div {transform:…

JVM常用调优参数 ——JVM篇

JVM常用性能调优参数详解 ​ 在学习完整个JVM内容后&#xff0c;其实目标不仅是学习了解整个JVM的基础知识&#xff0c;而是为了进行JVM性能调优做准备&#xff0c;所以以下的内容就是来说说JVM性能调优的知识。 一、性能调优 ​ 性能调优包含多个层次&#xff0c;比如&…

学习实践-Vicuna【小羊驼】(部署+运行)

1、Vicuna【小羊驼】-FastChat"更快的对话" 介绍 3 月底&#xff0c;UC伯克利开源大语言模型Vicuna来了&#xff0c;这是一个与 GPT-4 性能相匹配的 LLaMA 微调版本。“缺啥补啥缺啥练啥&#xff0c;傻子也突出”&#xff01; Vicuna 使用从 ShareGPT 收集的用户共…

生成对抗网络GAN

1.基本概念 生成对抗网络Generative Adversarial Networks&#xff08;GAN&#xff09;包含生成模型&#xff08;generative model&#xff09;和判别模型 (discriminative model) 两个模型。生成模型的任务是生成和原始数据相似的实例&#xff0c;判别模型的任务是判断给定的实…

四百左右音质好的蓝牙耳机有哪些?2023公认音质最好的蓝牙耳机排行

与有线耳机相比&#xff0c;蓝牙耳机有着功能多样、使用便捷的优点。最近看到很多人问&#xff0c;四百内音质好的蓝牙耳机有哪些&#xff1f;针对这个问题&#xff0c;我来给大家推荐几款音质最好的蓝牙耳机&#xff0c;一起来看看吧。 一、南卡小音舱Lite2蓝牙耳机 参考价&…

Mybatis(九)插件原理及应用

一、Mybatis的插件实现原理 Mybatis允许用户通过自定义拦截器的方式改变Sql的执行方式&#xff0c;例如在Sql执行时追加Sql分页语法&#xff0c;从而达到减缓分页查询的目的&#xff0c;用户自定义拦截器也被称为Mybatis插件。 我们先从插件的配置及解析过程来分析插件&#…

蓝奥声核心技术分享——基于物联网的无线智能标签刷新控制技术

1.技术背景 基于物联网的无线智能标签刷新控制技术指基于对目标场景状态变化的协同感知而获得触发响应并进行智能决策&#xff0c;属于蓝奥声核心技术--边缘协同感知(EICS&#xff09;技术的关键支撑性技术之一。该项技术涉及物联网边缘域的无线通信与智能控制技术领域。 物联…

学习同步异步的概念,并了解MQ消息队列

文章目录 一、 同步和异步1.1 同步调用1.2 异步调用 二、MQ1.1 介绍1.2 MQ的优点和使用场景 一、 同步和异步 1.1 同步调用 同步调用是一种程序调用方式&#xff0c;在该调用方式中&#xff0c;调用者发起一个请求&#xff0c;然后一直等待被调用者返回响应结果后再继续执行。…

wps - 使用宏来为每行标记序号

在WPS中遇到需要加序号的虽然可以用项目符符号来标注# 但或许用宏更厉害一些 WPS 的宏是一种自动化工具&#xff0c;可以通过编写宏代码来自动执行一些操作&#xff0c;例如创建和编辑文档、打印、格式化等。 WPS 宏的编写可以使用 VBA&#xff08;Visual Basic for Applicat…

236. 二叉树的最近公共祖先 ——【Leetcode每日一题】

236. 二叉树的最近公共祖先 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff…

inode和软硬链接

文章目录&#xff1a; 一、理解文件系统1.1 什么是inode1.2 磁盘了解1.2.1磁盘的硬件结构1.2.2 磁盘的分区1.2.3 EXT2文件系统 二、软硬链接2.1 软链接2.2 硬链接 一、理解文件系统 1.1 什么是inode inodes 是文件系统中存储文件元数据的数据结构。每个文件或目录都有一个唯一…

JavaSE学习进阶day06_01 数据结构(进阶)

第一章 数据结构&#xff08;温习数据结构的内容&#xff09; 1.1 树基本结构介绍 树具有的特点&#xff1a; 每一个节点有零个或者多个子节点 没有父节点的节点称之为根节点&#xff0c;一个树最多有一个根节点。 每一个非根节点有且只有一个父节点 名词含义节点指树中的…

第二届“威固新能源 GO野”,威固重塑新能源出行不凡体验

中国&#xff0c;上海&#xff0c;近日——全球特种材料公司伊士曼旗下汽车膜品牌威固&#xff08;V-KOOL&#xff09;&#xff0c;于近日开启了第二届“威固新能源 GO野”不凡之旅&#xff0c;通过专为新能源而来的创新产品与服务&#xff0c;引领高端新能源车主驶出城市生活的…

晨控可视化标签在资产管理上的应用及优势

晨控可视化标签在资产管理上的应用及优势 资产是企业功能的核心组成部分&#xff0c;是企业重要的基础设施建设。资产存在的形式各种各样&#xff0c;不仅具有价值高、流动性强、安全管理困难的特点&#xff0c;而且成为资产管理的重要环境之一。通过射频识别技术&#xff0c;…

【00-Java Web先导课】-如何进行IDEA的安装

前沿 Pycharm与IDEA激活教程一样&#xff0c;本篇以IDEA激活教程为例进行保姆级教学 文章目录 前沿一、支持系统二、软件版本1.引入库 三、软件下载教程1、点击网址进入jetbrains官网2、按照下图选择相应下载的软件3、按照如图选择需要下载的版本4、按照如下方式进行下载软件 四…

Web服务器

目录 什么是Web服务器&#xff1f; Web容器 Servlet Servlet 规范 Servlet 的API结构 编写Servlet servlet生命周期&#xff08;产生到销毁的过程&#xff09; 服务器产生响应信息的两种格式 什么是Web服务器&#xff1f; Web服务器是一个程序&#xff0c;用于接收客户…

【LeetCode: 718. 最长重复子数组 | 暴力递归=>记忆化搜索=>动态规划】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

Scillus | 来吧!它可以大大简化你的Seurat分析流程哦!~(一)(数据预处理)

1写在前面 太久没更了&#xff0c;真是累到极致&#xff0c;每天回到家都只想睡觉。&#x1f62d; 今天介绍一下Scillus包&#xff0c;是一个基于Seurat和ggplot2的R包&#xff0c;用于增强scRNA-seq数据的处理和可视化。&#x1f9d0; 它可以对Seurat对象进行多种类型的图形展…