Redux相关知识(什么是redux、redux的工作原理、redux的核心概念、redux的基本使用)(十一)
系列文章目录
第一章:React基础知识(React基本使用、JSX语法、React模块化与组件化)(一)
第二章:React基础知识(组件实例三大核心属性state、props、refs)(二)
第三章:React基础知识(事件处理、受控组件与非受控组件、高阶函数、组件的生命周期)(三)
第四章:React脚手架应用(创建脚手架、代理配置、ajax相关、组件通信)(四)
第五章:react-router5路由相关一(路由相关概念、基本使用、NavLink与NavLink的封装、Switch的使用、严格匹配、路由重定向、路由组件与一般组件的区别)(五)
第六章:react-router5路由相关二(嵌套路由、路由传参、replace、编程式路由导航、withRouter的使用、BrowserRouter与HashRouter的区别)(六)
第七章:React-Router6路由相关一(路由的基本使用、重定向、NavLink·、路由表、嵌套路由)(七)
第八章:React-Router6路由相关二(路由传参、编程式路由导航、路由相关hooks)(八)
第九章:React相关扩展一(setState、lazyLoad、Hooks相关)(九)
第十章:React相关扩展二(Fragment、Content、组件优化、render props、错误边界)(十)
第十一章:Redux相关知识(什么是redux、redux的工作原理、redux的核心概念、redux的基本使用)(十一)
第十二章:React-Redux相关知识(什么是react-redux、react-redux的原理、react-redux相关API、react-redux的基本使用)(十二)
文章目录
- 系列文章目录
- 一、什么是Redux
- 1.1 概念
- 1.2 何时使用?
- 1.3 redux的工作原理
- 二、核心概念
- 2.1 state
- 2.2 action
- 2.3 reducer(重要)
- 2.4 store
- 2.5 dispatch
- 2.6 subscribe(listener)
- 三、redux的基本使用(搭建redux环境)
一、什么是Redux
1.1 概念
Redux
是 JavaScript应用的状态容器
,提供可预测的状态管理。可以开发出行为稳定可预测的应用,运行于不同的环境(客户端、服务器、原生应用),并且易于测试。Redux
是一个使用叫做“action”
的事件来管理和更新应用状态的模式和工具库
,它以集中式Store的方式对整个应用中使用的状态进行集中管理
,其规则确保状态只能以可预测的方式更新。Redux
提供的模式和工具使您更容易理解应用程序中的状态何时、何地、为什么以及如何更新
,以及当这些更改发生时您的应用程序逻辑将如何表现。- 类似于vuex 但是不同于vuex,可以对状态进行管理。
1.2 何时使用?
- 在应用的大量地方,都存在大量的状态
- 应用状态会随着时间的推移而频繁更新
- 更新该状态的逻辑可能很复杂
- 中型和大型代码量的应用,很多人协同开发
- 不同身份的⽤户有不同的使⽤⽅式(⽐如普通⽤户和管理员)
- 与服务器⼤量交互,或者使⽤了WebSocket
- View要从多个来源获取数据
- 某个组件的状态,需要共享某个状态需要在任何地⽅都可以拿到
- ⼀个组件需要改变全局状态
- ⼀个组件需要改变另⼀个组件的状态
1.3 redux的工作原理
页面初始渲染时:
- 使用最顶层的 root reducer 函数创建 Redux store
store 调用一次 root reducer
,并将返回值保存为它的初始 state
- 当 UI 首次渲染时,
UI 组件访问 Redux store 的当前 state
,并使用该数据来决定要呈现的内容。 - 同时
监听store 的更新
,以便他们可以知道 state 是否已更改。
页面更新渲染时:
dispatch
一个action
到Redux store
,例如dispatch({type:'counter/increment'})
store
用之前的 state
和当前的 action 再次运行 reducer 函数
,并将返回值保存为新的 state
store
通知所有订阅过的 UI
,通知它们 store 发生更新
- 每个订阅过 store 数据的 UI 组件都会检查它们需要的 state 部分是否被更新。
发现数据被更新
的每个组件都强制使用新数据重新渲染
,紧接着更新网页
。
二、核心概念
应用的整体全局状态
以对象树的方式存放于单个 store
。 唯一改变状态树的方法
是创建 action
,一个描述发生了什么的对象,并将其 dispatch 给 store
。 要指定状态树如何响应 action 来进行更新
,你可以编写纯 reducer 函数
,这些函数根据旧 state 和 action 来计算新 state
。
2.1 state
- 托管给redux管理的状态
- 示例代码:
let state = { todos:[], params:{}
}
2.2 action
Action
Action
描述当前发⽣的事情。改变State的唯⼀办法
,就是使⽤Action。它会运送数据到 Store。- Action 本质上是 JavaScript 普通对象。
action
内必须使⽤
⼀个字符串类型的type字段
来表示将要执⾏的动作
。 - type 字段是一个字符串,给这个 action 一个描述性的名字,比如"todos/todoAdded"。
- action对象可以有其他字段,其中包含有关发生的事情的附加信息。按照惯例,我们将该信息放在名为data的字段中,也可放放到其他属性中,不过最好放到data中。
- 示例代码:
{ type: 'ADD_TODO', text: '去游泳馆' } { type: 'TOGGLE_TODO', index: 1 } { type: 'SET_VISIBILITY_FILTER', filter: 'completed' }
Action Creator
action creator
是一个创建并返回一个 action 对象的函数
。它的作用是让你不必每次都手动编写 action对象示例代码:
const addTodo = data => ({type: 'todos/todoAdded',data})
2.3 reducer(重要)
reducer
是一个函数
,接收当前的state和一个action 对象
,必要时决定如何更新状态,并返回新状态。函数签名是:(state, action) => newState
。可以将reducer 视为一个事件监听器,它根据接收到的action(事件)类型处理事件。Reducer 必需符合以下规则:
仅使用 state 和 action 参数计算新的状态值
禁止直接修改 state
。必须通过复制现有的 state 并对复制的值进行更改的方式来做不可变更新禁止任何异步逻辑、依赖随机值或导致其他“副作用”的代码
reducer 函数内部的逻辑通常遵循以下步骤:
- 检查 reducer 是否联系这个 action
- 如果是,则复制 state,使用新值更新 state 副本,然后返回新 state
- 否则,返回原来的 state 不变
- 检查 reducer 是否联系这个 action
示例代码:
// 初始化状态 const initialState = { value: 0, index: 1 }function counterReducer(preState=initialState, action) {//从action对象中获取:type、dataconst {type,data} = action//根据type决定如何加工数据switch (type) {case 'increment': //如果是加return { ...preStatevalue:preState.value + data}case 'decrement': //若果是减return { ...preStatevalue:preState.value - data}default:// 返回prestate 不变return preState} }
2.4 store
当前
Redux 应用的状态存在于
一个名为store
的对象中。store
是通过传入一个reducer来创建的
,并且有一个getState 的方法
,它返回当前状态值
。Store
就是保存数据的地⽅,可以把它看成⼀个容器。整个应⽤只能有⼀个Store。Redux提供createStore
这个函数,⽤来⽣成Store
。示例代码:
//引入createStore,专门用于创建redux中最为核心的store对象 // 旧版本的引入 // import {createStore} from 'redux' // 新版本的引入 import { legacy_createStore as createStore } from 'redux' //引入为Count组件服务的reducer import reducer from './reducer' //暴露store export default createStore(reducer) /* 如果该仓库用多个reducer,则使用combineReducers函数来合并reducer,可以通过combineReducers组合多个Reducer,然后通过createStore来创建状态机。*/ const store2=createStore(combineReducers({todos,counter, }));
或者直接使用@reduxjs/toolkit包中的configureStore方法来生成store
import { configureStore } from '@reduxjs/toolkit' const store = configureStore({ reducer})
仓库创建好了之后,将store引入到需要使用仓库的组件中。
import store from './store/index.js' // 分发动作 store.dispatch({type:'',data:''}) // 获取仓库数据 store.getState();
2.5 dispatch
Redux store 有一个方法叫
dispatch
。更新 state 的唯一方法
是调用 store.dispatch() 并传入一个action对象
。store 将执行所有reducer函数并计算出更新后的state,调用 getState()
可以获取新state。示例代码:
store.dispatch({ type: 'counter/increment' }) console.log(store.getState()) // {value: 1}
dispatch 一个 action 可以形象的理解为 "触发一个事件"
。发生了一些事情,我们希望 store
知道这件事。Reducer 就像事件监听器一样,当它们收到关注的 action 后,它就会更新 state 作为响应。我们通常调用 action creator 来调用 action
:示例代码:
const increment = () => {return {type: 'counter/increment'} } // 分发动作 store.dispatch(increment()) console.log(store.getState())
2.6 subscribe(listener)
添加一个变化监听器
。每当dispatch action 的时候就会执行
,state
树中的一部分可能已经变化。你可以在回调函数里调用 getState() 来拿到当前 state
。你可以在变化监听器里面进行
dispatch(),如果需要解绑这个变化监听器,执行 subscribe 返回的函数即可。参数listener (Function): 每
当 dispatch action 的时候都会执行的回调
。state 树中的一部分可能已经变化。你可以在回调函数里调用 getState() 来拿到当前 state。返回值(Function): 一个可以解绑变化监听器的函数。
// 监听方法一 store.subscribe(() => {this.setState({...store.getState()}); }); //订阅者做的事情// 监听方法二 store.subscribe(()=>{ReactDOM.render(<App/>,document.getElementById('root')) })
三、redux的基本使用(搭建redux环境)
安装
npm install redux
主要API
createStore(reducer, [preloadedState], [enhancer])
创建仓库combineReducers(reducers)
合并reducerapplyMiddleware(...middlewares)
应用中间件
store相关API
store.getState()
获取仓库中的状态store.dispatch(action)
分发到某个动作store.subscribe(listener)
订阅仓库内状态更新replaceReducer(nextReducer)
替换reducer
代码案例片段:
index.jsimport React from 'react' import ReactDOM from 'react-dom' import App from './App' import store from './redux/store'ReactDOM.render(<App/>,document.getElementById('root'))store.subscribe(()=>{ReactDOM.render(<App/>,document.getElementById('root')) })
App.js
import React, { Component } from 'react' import Count from './components/Count'export default class App extends Component {render() {return (<div><Count/></div>)} }
redux/count_action.js(该文件专门为Count组件生成action对象)
//同步action,就是指action的值为Object类型的一般对象 export const createIncrementAction = data => ({type:'increment',data}) export const createDecrementAction = data => ({type:'decrement',data})//异步action,就是指action的值为函数,异步action中一般都会调用同步action,异步action不是必须要用的。 export const createIncrementAsyncAction = (data,time) => {return (dispatch)=>{setTimeout(()=>{dispatch(createIncrementAction(data))},time)} }
redux/count_reducer.js
/* 1.该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数2.reducer函数会接到两个参数,分别为:之前的状态(preState),动作对象(action) */ const initState = {value:0,index:1 } //初始化状态 export default function countReducer (preState = initState, action) {console.log('preState:',preState);console.log('action:',action);//从action对象中获取:type、dataconst { type, data } = action//根据type决定如何加工数据switch (type) {case 'increment': //如果是加return {...preState,value: preState.value + data}case 'decrement': //若果是减return {...preState,value: preState.value - data}default:return preState} }
redux/store.js
/* 该文件专门用于暴露一个store对象,整个应用只有一个store对象 *///引入createStore,专门用于创建redux中最为核心的store对象 // 旧版 // import { createStore } from 'redux' //新版 import { legacy_createStore as createStore, applyMiddleware } from 'redux' //引入为Count组件服务的reducer import countReducer from './count_reducer' //引入redux-thunk,用于支持异步action import thunk from 'redux-thunk' //暴露store export default createStore(countReducer, applyMiddleware(thunk))
components/Count.jsx
import React, { Component } from 'react' //引入store,用于获取redux中保存状态 import store from '../../redux/store' //引入actionCreator,专门用于创建action对象 import {createIncrementAction,createDecrementAction,createIncrementAsyncAction } from '../../redux/count_action'export default class Count extends Component {state = {carName:'奔驰c63'}/* componentDidMount(){//检测redux中状态的变化,只要变化,就调用renderstore.subscribe(()=>{this.setState({})})} *///加法increment = ()=>{const {value} = this.selectNumberstore.dispatch(createIncrementAction(value*1))}//减法decrement = ()=>{const {value} = this.selectNumberstore.dispatch(createDecrementAction(value*1))}//奇数再加incrementIfOdd = ()=>{const {value} = this.selectNumberconst count = store.getState()if(count % 2 !== 0){store.dispatch(createIncrementAction(value*1))}}//异步加incrementAsync = ()=>{const {value} = this.selectNumber// setTimeout(()=>{store.dispatch(createIncrementAsyncAction(value*1,500))// },500)}render() {return (<div><h1>当前求和为:{store.getState()}</h1><select ref={c => this.selectNumber = c}><option value="1">1</option><option value="2">2</option><option value="3">3</option></select> <button onClick={this.increment}>+</button> <button onClick={this.decrement}>-</button> <button onClick={this.incrementIfOdd}>当前求和为奇数再加</button> <button onClick={this.incrementAsync}>异步加</button> </div>)} }
运行结果:
Redux相关知识(什么是redux、redux的工作原理、redux的核心概念、redux的基本使用)(十一)相关推荐
- 路由相关知识,静态路由、默认路由、浮动路由的概念以及基本设置
路由相关知识,静态路由.默认路由.浮动路由的概念以及基本设置 选取最佳路由时的标准 路由表 路由表的形成 静态路由概念 静态路由的优点和缺点 默认路由 浮动路由 路由协议分类 静态路由.默认路由.浮动 ...
- 光立方原理讲解_电工基础知识——光电耦合器的分类、工作原理和检测以及应用...
大家好,今天我们主要讲解一下光电耦合器的分类.工作原理和检测以及其在生活中的应用. 光电耦合器 1.光电耦合器的分类 光电耦合器分两类:普通光电耦合器和线性光电耦合器.普通光电耦合器的输入.输出间传输 ...
- 《涨知识啦30》-太阳能电池基本工作原理
当光照射到PN结上时,PN结区会产生电子-空穴对,结区中的部分非平衡载流子将以复合的形式湮灭,没有参与复合的非平衡载流子则在PN结区电场的作用下进行输运:电子进入N区,空穴进入P区,因此N区中过剩的电 ...
- 硬件基础知识--(10)三极管的工作原理
一.很多初学者都会认为三极管是两个 PN 结的简单凑合(如图1).这种想法是错误的,两个二极管的组合不能形成一个三极管.我们以 NPN 型三极管为例(见图 2 ),两个 PN 结共用了一个 P 区 - ...
- 《涨知识啦29》-DBR的工作原理及其在VCSEL中的作用
分布式布拉格(Distributed Bragg Reflection,简称DBR)反射镜是垂直腔面发射激光器(Vertical-Cavity Surface-Emitting Laser,简称VCS ...
- Redux 主要知识学习总结
文章出自个人博客 https://knightyun.github.io/2020/11/29/js-redux-summary,转载请申明 概念 Redux 作为一个状态管理器,可以应用于多种 we ...
- 【React.js 06】Redux基础知识
Redux是一个专注于状态管理的库,和React是解耦的,用Angular和Vue都可以使用Redux.其具有一个单一状态,单向数据流的特性. Redux概念 redux有一个store,记录所有的s ...
- redux相关学习资源
很多学习资料,直接在SF.掘金搜索关键词redux源码等可以获得. redux参考版本3.6或3.7.2 redux-thunk看1.0.1 1.redux源码分析之四:compose函数 ...
- Redux 核心概念
http://gaearon.github.io/redux/index.html ,文档在 http://rackt.github.io/redux/index.html .本文不是官方文档的翻译. ...
最新文章
- void main()是错的!
- 2021年人工神经网络第一次作业要求
- 【报错】No match for argument: mysql-community-server Error: Unable to find a match: mysql-community-s
- 二分法(三种基本模版)
- python怎么编辑文件_如何使用python中的方法对文件进行修改文件名
- 写代码需要注意的几方面
- 爬虫+pyecharts数据分析实例:当当网
- Spring beans配置方案(二) 学习笔记
- 未来网闸的发展趋势(实际应用需求,解决方案)
- [Cocos Creator] 制作简版消消乐(四):实现消除算法
- ev3无需使用计算机编程,Legoev3机器人怎么编程.docx
- python动态调用函数
- 您的Window许可证即将过期的一种解决办法
- 3小时入门微信小程序开发 --公开课学习笔记
- CCF [201703-1] 分蛋糕(C++)
- 「解析」正则化 DropPath
- wifi mesh组网
- 一文掌握GSEA,超详细教程!
- Kali/Ubuntu GVM (openvas)安装及使用
- 虚幻引擎学习笔记——Month1 Week1
热门文章
- svg动画,渐变,阴影
- 计算机联锁驱采故障查找,EI32-JD型计算机联锁驱动、采集故障处理方法.pdf
- qq空间秒赞技术是如何实现的?
- Caused by: java.lang.ClassNotFoundException: org.springframework.boot.context.properties.Configurati
- ios沙箱软件_iOS 开发之沙盒机制
- python围圈报数 青少年编程电子学会python编程等级考试三级真题解析2021年6月
- 一个 Web 项目的创建及配置(完整版)
- 怀旧服一直显示正在登录服务器,怀旧服显示正在登录游戏服务器
- linux signal历史log,nginx错误signal process started错误error.log日志显示signal process started错误解决方法...
- venv 创建虚拟环境并激活