Redux梳理总结一文通透

您所在的位置:网站首页 redux使用方法 Redux梳理总结一文通透

Redux梳理总结一文通透

2023-01-22 05:11| 来源: 网络整理| 查看: 265

第6章:redux 一、redux理解 1. 学习文档 英文文档: https://redux.js.org/中文文档: http://www.redux.org.cn/Github: https://github.com/reactjs/redux 2. redux是什么

redux是一个专门用于做状态管理的JS库(不是react插件库)。

它可以用在react, angular, vue等项目中, 但基本与react配合使用。

作用: 集中式管理react应用中多个组件共享的状态。

安装:npm i redux

3. 什么情况下使用redux

某个组件的状态,需要让其他组件可以随时拿到(共享)。

一个组件需要改变另一个组件的状态(通信)。

总体原则:能不用就不用, 如果不用比较吃力才考虑使用。

4. redux工作流程

二、redux的三个核心概念 1. action

action 是 store 中唯一的数据来源,一般来说,我们会通过调用 store.dispatch 将 action 传到 store,我们需要传递的 action 是一个对象,它必须要有一个 type 值

动作的对象

包含两个属性

type:标识属性,值为字符串,唯一,必要属性data:数据类型,值类型任意,可选属性

例子:{ type: 'ADD_STUDENT',data:{name: 'tom',age:18} }

/* 该文件专门为Count组件生成action对象 */ import { INCREMENT, DECREMENT } from "./constant"; export const createIncrementAction = (data) => ({ type: INCREMENT, data }); export const createDecrementAction = (data) => ({ type: DECREMENT, data }); 2. reducer

在 Reducer 中,我们需要指定状态的操作类型,要做怎样的数据更新,因此这个类型是必要的。reducer 会根据 action 的指示,对 state 进行对应的操作,然后返回操作后的 state

用于初始化状态加工状态

根据旧的state和action, 产生新的state的纯函数。

作为createStore的参数

代码:

/* 1.该文件用于创建一个为Count组件服务的reducer,reducer的本质是一个函数 2.reducer会接受到两个参数,分别为之前的状态(preState),动作对象(action) */ import { INCREMENT, DECREMENT } from "./constant"; const initState = 0; // 初始化状态 export default function countReducer(preState = initState, action) { // console.log(preState); const { type, data } = action; switch (type) { case INCREMENT: // 加 return preState + data; case DECREMENT: // 减 return preState - data; default: return preState; } } 3. store

store 是 Redux 的核心,可以理解为是 Redux 的数据中台,我们可以将任何我们想要存放的数据放在 store中,在我们需要使用这些数据时,我们可以从中取出相应的数据。因此我们需要先创建一个 store,在 Redux 中可以使用 createStoreAPI 来创建一个store

在生产中,我们需要在 src 目录下的 redux 文件夹中新增一个 store.js 文件,在这个文件中,创建一个 store 对象,并暴露它

将state、action、reducer联系在一起的对象

如何得到此对象?

import {createStore} from 'redux' import reducer from './reducers' const store = createStore(reducer)

此对象的功能?

getState(): 得到state

dispatch(action): 分发action, 触发reducer调用, 产生新的state

subscribe(listener): 注册监听, 当产生了新的state时, 自动调用

代码:

/* 该文件专门用于暴露一个store对象,整个应用只有一个store对象 */ // 引入createStore import { legacy_createStore } from "redux"; // 引入为Count组件服务的reducer import countReducer from "./count_reducer"; // 暴露store export default legacy_createStore(countReducer); 三、redux核心API 1. createstore(reducer)

作用:创建包含指定reducer的store对象

2. store对象

作用: redux库最核心的管理对象

它内部维护着:

statereducer

核心方法:

getState():获取当前时刻的 storedispatch(action):通过 store 中的 dispatch 方法来派生一个 action 对象给 storesubscribe(listener):subscribe方法,这个方法可以帮助我们订阅 store 的改变,只要 store发生改变,这个方法的回调就会执行

具体编码:

store.getState()

store.dispatch({type:'INCREMENT', number})

store.subscribe(render)

store.subscribe(() => { ReactDOM.render( , document.getElementById('root')) }) 3. applyMiddleware()

作用:应用上基于redux的中间件(插件库)

import thunk from 'redux-thunk' export default createStore(countReducer, applyMiddleware(thunk)) 4. combineReducers()

作用:合并多个reducer函数

5. redux异步编程

redux默认是不能进行异步处理的,

某些时候应用中需要在redux中执行异步任务(ajax, 定时器)

使用异步中间件

npm install --save redux-thunk

import thunk from 'redux-thunk' export default createStore(countReducer, applyMiddleware(thunk))

代码:

export const createIncrementAsyncAction = (data, time) => { // 无需引入 store ,在调用的时候是由 store 调用的 return (dispatch) => { setTimeout(() => { dispatch(createIncrementAction(data)) }, time) } }

注意:异步 action 不是必须要写的,完全可以自己等待异步任务的结果后再去分发同步action

采用 react-thunk 能让异步代码像同步代码一样执行,在 redux 中我们也是可以实现异步的,但是这样我们的代码中会有很多异步的细节,这不是我们想看到的,利用 react-thunk 之类的库,就能让我们只关心我们的业务

6. Redux 三大原则

理解好 Redux 有助于我们更好的理解接下来的 React -Redux

第一个原则

单向数据流:整个 Redux 中,数据流向是单向的

UI 组件 —> action —> store —> reducer —> store

第二个原则

state 只读:在 Redux 中不能通过直接改变 state ,来控制状态的改变,如果想要改变 state ,则需要触发一次 action。通过 action 执行 reducer

第三个原则

纯函数执行:每一个reducer 都是一个纯函数,不会有任何副作用,返回是一个新的 state,state 改变会触发 store 中的 subscribe### 四、react-redux

在前面我们学习了 Redux ,我们在写案例的时候,也发现了它存在着一些问题,例如组件状态无法公用,每一个状态组件都需要通过订阅来监视,状态更新会影响到全部组件更新,面对着这些问题,React 官方在 redux 基础上提出了 React-Redux 库,专门用来简化react应用中使用redux

安装:npm i react-redux

1. 容器组件和 UI 组件

UI组件

只负责 UI 的呈现,不带有任何业务逻辑

通过props接收数据(一般数据和函数)

不使用任何 Redux 的 API

一般保存在components文件夹下

容器组件

负责管理数据和业务逻辑,不负责UI的呈现

使用 Redux 的 API

一般保存在containers文件夹下 在这里插入图片描述 要实现容器组件和 UI 组件的连接,我们需要通过 connect 来实现

2. Provider

由于我们的状态可能会被很多组件使用,所以 React-Redux 给我们提供了一个 Provider 组件,可以全局注入 redux 中的 store ,只需要把 Provider 注册在根部组件即可

在 src 目录下的 index.js 文件中,引入 Provider ,直接用 Provider 标签包裹 App 组件,将 store 写在 Provider 中即可。这样我们在 App.jsx 文件中,组件无需手写指定 store ,即可使用 store

ReactDOM.render( , document.getElementById("root") ); 3. connect

在前面我们看到的 react-redux 原理图时,我们会发现容器组件需要给 UI 组件传递状态和方法,并且是通过 props 来传递,看起来很简单。但是,我们会发现容器组件中似乎没有我们平常传递 props 的情形。

因为UI组件是通过**connect()(UI组件)**这样的形式连接。这时候就需要继续研究一下容器组件中的唯一一个函数 connect

connect 方法是一个连接器,用于连接容器组件和 UI 组件的高阶函数,它第一次执行时,接收4个参数,这些参数都是可选的,第一次执行时的四个参数:mapStateToProps 、mapDispatchToProps 、mergeProps、options,它执行的执行的结果还是一个函数,第二次执行接收一个 UI 组件参数

mapStateToProps:函数

建立了UI 组件和容器组件间的状态传递

代码:const mapStateToProps = state => ({ count: state })

它接收 state 作为参数,并且返回一个对象,这个对象标识着 UI 组件的同名参数

返回的对象中的 key 就作为传递给 UI 组件 props 的 key,value 就作为 props 的 value

UI 组件中直接通过 props 来读取 count 值

当前求和为:{this.props.count}

mapDispatchToProps:函数或者对象

connect 接受的第二个参数是 mapDispatchToProps,它是用于建立 UI 组件的参数到 store.dispacth 方法的映射

我们可以把参数写成对象形式,在这里面定义 action 执行的方法,例如 jia 执行什么函数,jian 执行什么函数?

我们都可以在这个参数中定义,如下定义了几个方法对应的操作函数

{ jia: createIncrementAction, jian: createDecrementAction, jiaAsync: createIncrementAsyncAction }

自动调用dispatch

似乎少了点什么,我们在这里调用了函数,创建了 action 对象,但是好像 store 并没有执行 dispatch ,那是不是断了呢?执行不了呢?

其实这里 react-redux 已经帮我们做了优化,当调用 actionCreator 的时候,会立即发送 action 给 store 而不用手动的 dispatch

即connect(mapStateToProps, mapDispatchToProps)(CountUI);

4. react-redux的优化

容器组件和UI组件整合一个文件

无需自己给容器组件传递store,给包裹一个即可。

使用了react-redux后也不用再自己检测redux中状态的改变了,容器组件可以自动完成这个工作。即不用写一下代码:

// 监测redux中状态的改变,如果redux的状态发生了改变,那么重新渲染App组件 store.subscribe(() => { ReactDOM.render(, document.getElementById("root")); });

mapDispatchToProps也可以简单的写成一个对象

一个组件要和redux“打交道”要经过哪几步?

定义好UI组件—不暴露

引入connect生成一个容器组件,并暴露,写法如下:

connect( state => ({ key : value }), //映射状态 { key : xxxxxAction } //映射操作状态的方法 )(UI组件)

在UI组件中通过this.props.xxxxxxx读取和操作状态

5. react-redux数据共享

定义一个Pserson组件,和Count组件通过redux共享数据。

为Person组件编写:reducer、action,配置constant常量。

重点:Person的reducer和Count的Reducer要使用combineReducers进行合并, 合并后的总状态是一个对象!!!

// 暴露store export default legacy_createStore( combineReducers({ count: countReducer, persons: personReducer }), applyMiddleware(thunk) );

交给store的是总reducer,最后注意在组件中取出状态的时候,记得“取到位”。

export default connect( (state) => ({ personList: state.persons, count: state.count }), { addPerson: createAddPersonAction, } )(Person);

优化:reducers文件夹中,编写index.js专门用于汇总并暴露所有的reducer

6. react-redux开发者工具的使用

下载Chrome浏览器插件 地址:Redux-DevTools 浏览器调试工具

在项目中安装redux-devtools-extension

npm i redux-devtools-extension

在store中进行配置

// 引入redux-devtools-extension import { composeWithDevTools } from "redux-devtools-extension"; // 暴露store export default legacy_createStore( combineReducers({ count: countReducer, persons: personReducer }), composeWithDevTools(applyMiddleware(thunk)) );

成功配置如下 在这里插入图片描述

7. 纯函数

如果函数的调用参数相同, 则永远返回相同的结果. 它不依赖于程序执行期间函数外部任何状态或数据的变化, 只依赖于传入的参数

必须遵守以下一些约束

不得改写参数数据

不会产生任何副作用,例如网络请求,输入和输出设备

不能调用Date.now()或者Math.random()等不纯的方法

redux的reducer函数必须是一个纯函数

本文来自博客园,作者:你就是星光,转载请注明原文链接:https://www.cnblogs.com/xzqyl/p/17045385.html



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3