【react】Redux基础用法

embedded/2024/11/8 23:55:25/

1. Redux基础用法

Redux 是一个用于 JavaScript 应用的状态管理库,它不依赖于任何 UI库,但常用于与 React 框架配合使用。它提供了一种集中式的状态管理方式,将应用的所有状态保存在一个单一的全局 Store(存储)中,使得状态的变化和共享变得更加可控和可预测。

Redux 的核心概念:

  • Store
    Redux 的 Store 是一个对象,存储了应用的全部状态。应用中只有一个 Store,作为单一数据源。任何组件需要访问状态时都会从这个 Store 中获取数据。

  • Action
    Action 是一个简单的 JavaScript 对象,用**来描述要执行的状态变化。**它通常包含两个部分:type(字符串,描述 Action 的类型)和 payload(可选,用来传递需要修改的数据信息)。Action 是 Redux 中唯一触发状态更新的方式。

  • Reducer
    Reducer 是一个纯函数,定义了应用在接收到不同 Action 时如何更新状态。它接收当前的状态和 Action,返回一个新的状态对象。

  • Dispatch
    Dispatch 是 Redux 中触发 Action 的方法。调用 store.dispatch(action) 可以将 Action 发送到 Store,从而触发 Reducer 更新状态。

  • Selectors
    Selectors 是从 Store 中获取特定状态的函数,主要用于简化和集中获取逻辑,避免直接访问 Store 造成的代码冗余。

  • Middleware
    Redux 中间件是在 dispatch 和 reducer 之间的一个逻辑层,可以用于处理异步操作(如 redux-thunk)或记录状态变化(如 redux-logger)。中间件增强了 Redux,使其能够处理复杂的逻辑和副作用。

简单计数器案例:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<script src="https://cdn.bootcdn.net/ajax/libs/redux/4.2.0/redux.min.js"></script><body><button id="increment">+</button><span id="count">0</span><button id="decrement">-</button>
</body><script>// 1.定义reducer函数// 作用:根据不同的action对象,返回不同的新的state// state:管理的数据初始状态// action:对象 type 标记当前想要做什么样的修改function reducer(state = { count: 0 }, action) {// 数据不可变:基于原始状态生成一个新的状态if (action.type === 'INCREMENT') {return { count: state.count + 1 }}if (action.type === 'DECREMENT') {return { count: state.count - 1 }}return state}// 2. 使用reducer函数创建store对象const store = Redux.createStore(reducer)// 3. 通过store对象的dispatch,修改store中的数据const inBtn = document.getElementById('increment')const deBtn = document.getElementById('decrement')inBtn.addEventListener('click', () => {store.dispatch({ type: 'INCREMENT' })})deBtn.addEventListener('click', () => {store.dispatch({ type: 'DECREMENT' })})// 4. 监听store中数据的变化//每次state发生变化的时候自动执行store.subscribe(() => {console.log('store数据变化了', store.getState())document.getElementById('count').innerText = store.getState().count})
</script>
</html>

2. React中使用Redux

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

  1. Redux Toolkit(RTK): 官方推荐编写Redux逻辑的方式,是一套工具的集合,简化书写方式
  2. react-redux:用来 链接 Redux和 React组件的中间件
npm install @reduxjs/toolkit react-redux

目录结构:新建store文件夹,将子模块放在modules目录下,index.js为store入口文件。

创建 slice 需要一个字符串名称来标识 slice,一个初始 state 值,以及一个或多个 reducer 函数来定义如何更新 state。创建 slice 后,我们可以导出生成的 Redux action creators 和整个 slice 的 reducer 函数。

/store/modules/counterStore.js

import {createSlice} from '@reduxjs/toolkit'const counterSlice = createSlice({// 标识 slice的字符串名称name:'counter',// 初始化stateinitialState:{count:0},// 修改state的方法(同步方法reducers:{increment(state,action){// 修改时的传参会放在ction.payload属性上state.count += action.payload},decrement(state,action){state.count -= action.payload}}
})// 从 counterSlice.actions中解构
export  const {increment,decrement} = counterSlice.actions
export default counterSlice.reducer

接下来,我们需要从 counter slice 中导入 reducer 函数,并将其添加到我们的 store 中。通过在 reducer 参数中定义一个字段,我们告诉 store 使用这个 slice reducer 函数来处理对该状态的所有更新。

/store/index.js

import { configureStore } from "@reduxjs/toolkit";// 导入子模块reducer
import counterReducer from "./modules/counterStore";
// 通过configureStore来创建一个store
const store =configureStore({reducer: {counter: counterReducer,},
});
export default store

提供store
导入我们刚刚创建的 Redux store,在你的 <App> 周围放一个 <Provider>,然后将 store 作为 prop 传递

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { Provider } from "react-redux";
import store from "./store";// 将App组件渲染到id为root的DOM元素中
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();

读取store中的数据: 使用useSelector函数

修改store中的数据: 使用useDispatch函数,并根据需要 dispatch action

import { useDispatch, useSelector } from "react-redux";
import { increment, decrement } from "./store/modules/counterStore";
function App() {const { count } = useSelector((state) => state.counter);const dispatch = useDispatch();return (<div><button onClick={() => dispatch(decrement(1))}>-</button>{count}<button onClick={() => dispatch(increment(1))}>+</button></div>);
}export default App;

异步请求操作:

  1. 创建store的写法保持不变,配置好同步修改状态的方法
  2. 单独封装一个函数,在函数内部return一个新函数,在新函数中
    2.1 封装异步请求获取数据
    2.2 调用同步actionCreater传入异步数据生成一个action对象,并使用dispatch提交

/store/modules/sentenceStore.js

import { createSlice } from "@reduxjs/toolkit";
// 先安装npm i axios
import axios from "axios";const sentenceSlice = createSlice({name: "sentence",initialState: {sentence: {},},reducers: {setSentence(state, action) {state.sentence = action.payload;},},
});
const { setSentence } = sentenceSlice.actions;
// 获取异步请求数据
const getSentence = () => {return async (dispatch) => {const { data } = await axios.get("https://api.xygeng.cn/one");dispatch(setSentence(data.data));};
};
export { getSentence };    
export default sentenceSlice.reducer;

/store/index.js

import { configureStore } from "@reduxjs/toolkit";// 导入子模块reducer
import counterReducer from "./modules/counterStore";
import sentenceReducer from "./modules/sentenceStore";const store = configureStore({reducer: {counter: counterReducer,sentence: sentenceReducer,},
});
export default store;

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

import { useDispatch, useSelector } from "react-redux";
import { increment, decrement } from "./store/modules/counterStore";
import { getSentence } from "./store/modules/sentenceStore";
import { useEffect } from "react";
function App() {const { count } = useSelector((state) => state.counter);const { sentence } = useSelector((state) => state.sentence);// 通过dispatch触发action,来更新state状态const dispatch = useDispatch();// 使用useEffect触发异步请求useEffect(() => {dispatch(getSentence());}, [dispatch]);return (<div><button onClick={() => dispatch(decrement(1))}>-</button>{count}<button onClick={() => dispatch(increment(1))}>+</button><div>{" "}{sentence.content}--{sentence.name}</div></div>);
}export default App;

👻Redux 官网教程

3. Redux调试工具

google商城里搜索:
在这里插入图片描述

在这里插入图片描述


http://www.ppmy.cn/embedded/136022.html

相关文章

智能存储解决方案:探索 TDengine 的多级存储功能

在当今数据驱动的时代&#xff0c;如何高效地存储和管理海量数据已成为企业面临的一大挑战。为了应对这一需求&#xff0c;TDengine Enterprise 不仅支持使用对象存储&#xff08;S3&#xff09;&#xff0c;还早已引入了独特的多级存储功能。这一功能不仅能够降低存储成本&…

复刻OpenAI O1大模型

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;编程探索专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年11月8日15点40分 点击开启你的论文编程之旅https://www.aspiringcode.com/content?id17266599315514&uid40b33030de4d4898a…

可视化神经网络训练tensorflow.org

通过图像和动画的形式&#xff0c;解释深度学习是如何一步步简化复杂的事物的。 能够设置数据分布类型和测试集比例&#xff0c;批量大小、隐藏层、神经元个数&#xff0c;点击运行后就能直观的看到神经网络的训练过程演示&#xff0c;简直是深度学习初学者的福音。 TensorFl…

非计算机背景但是想从事医学AI研究,需要掌握的编程语言|个人观点·24-11-08

小罗碎碎念 目前&#xff0c;我们从事医学AI研究的&#xff0c;接触的最多的两种编程语言应该就是R和Python了。那么初学者很容易提出一个疑问&#xff0c;**我想从事医学AI相关的研究的话&#xff0c;应该学哪些编程语言呢&#xff1f;**在文章的开头&#xff0c;我可以先给出…

音视频入门基础:H.264专题(17)——FFmpeg源码中,获取H.264视频的profile的实现

音视频入门基础&#xff1a;H.264专题系列文章&#xff1a; 音视频入门基础&#xff1a;H.264专题&#xff08;1&#xff09;——H.264官方文档下载 音视频入门基础&#xff1a;H.264专题&#xff08;2&#xff09;——使用FFmpeg命令生成H.264裸流文件 音视频入门基础&…

聊一聊Elasticsearch的基本原理与形成机制

1、搜索引擎的基本原理 通常搜索引擎包括&#xff1a;数据采集、文本分析、索引存储、搜索等模块&#xff0c;它们之间的协作流程如下图&#xff1a; 数据采集模块负责采集需要搜索的数据源。 文本分析模块是将结构化数据中的长文本切分成有实际意义的词&#xff0c;这样用户…

泷羽sec学习打卡-shodan扫描5

声明 学习视频来自B站UP主 泷羽sec,如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 关于shodan的那些事儿-5 一、shodan5如何利用shodan去搜索一个网段的&#xff1f;网段各个参数是什么意思…

C++20 STL CookBook2 更强大的编译时 + 安全比较 + spaceship比较符

目录 使用编译时vector和字符串相关的上下文变量 安全的比较整数 <> :) 使用编译时vector和字符串相关的上下文变量 在大部分C语言程序中&#xff0c;我见过不少人是这样使用常量字符串的&#xff1a; #define STR "Hello, C" 然后可能传递进入一些函数做…