react-redux学习
本文于784天之前发表,文中内容可能已经过时。
React-Redux介绍
为什么要使用 React-Redux 绑定库?
React 和 Redux 是两个独立的库,两者之间职责独立。因此,为了实现在 React 中使用 Redux 进行状态管理 ,就需要一种机制,将这两个独立的库关联在一起。这时候就用到 React-Redux 这个绑定库了。
- 作用:为 React 接入 Redux,实现在 React 中使用 Redux 进行状态管理。
- react-redux 库是 Redux 官方提供的 React 绑定库。
基本使用
react-redux 的使用分为两大步:1 全局配置(只需要配置一次) 2 组件接入(获取状态或修改状态)
先看全局配置:
步骤:
- 安装 react-redux:
yarn add react-redux
- 从 react-redux 中导入 Provider 组件
- 导入创建好的 redux 仓库
- 使用 Provider 包裹整个应用
- 将导入的 store 设置为 Provider 的 store 属性值
核心代码:
src/index.js 中:
1 | // 导入 Provider 组件 |
获取状态useSelector
useSelector
:获取 Redux 提供的状态数据- 参数:selector 函数,用于从 Redux 状态中筛选出需要的状态数据并返回
- 返回值:筛选出的状态
1 | import { useSelector } from 'react-redux' |
例:
1 | import { useSelector } from 'react-redux' |
分发动作useDispatch
useDispatch
:拿到 dispatch 函数,分发 action,修改 redux 中的状态数据语法:
1
2
3
4
5
6
7import { useDispatch } from 'react-redux'
// 调用 useDispatch hook,拿到 dispatch 函数
const dispatch = useDispatch()
// 调用 dispatch 传入 action,来分发动作
dispatch( action )
例:
1 | import { useDispatch } from 'react-redux' |
理解 Redux 数据流
- 任何一个组件都可以直接接入 Redux,也就是可以直接:1 修改 Redux 状态 2 接收 Redux 状态
- 并且,只要 Redux 中的状态改变了,所有接收该状态的组件都会收到通知,也就是可以获取到最新的 Redux 状态
- 这样的话,两个组件不管隔得多远,都可以直接通讯了
代码结构
在使用 Redux 进行项目开发时,不会将 action/reducer/store 都放在同一个文件中,而是会进行拆分
可以按照以下结构,来组织 Redux 的代码:
1 | /store --- 在 src 目录中创建,用于存放 Redux 相关的代码 |
ActionType的使用
Action Type 指的是:action 对象中 type 属性的值
Redux 项目中会多次使用 action type,比如,action 对象、reducer 函数、dispatch(action) 等
目标:集中处理 action type,保持项目中 action type 的一致性
action type 的值采用:
'domain/action'(功能/动作)形式
,进行分类处理,比如,- 计数器:
'counter/increment'
表示 Counter 功能中的 increment 动作 - 登录:
'login/getCode'
表示登录获取验证码的动作 - 个人资料:
'profile/get'
表示获取个人资料
- 计数器:
步骤:
- 在 store 目录中创建
actionTypes
目录或者constants
目录,集中处理 - 创建常量来存储 action type,并导出
- 将项目中用到 action type 的地方替换为这些常量,从而保持项目中 action type 的一致性
1 | // actionTypes 或 constants 目录: |
注:额外添加 Action Type 会让项目结构变复杂,此操作可省略。但,domain/action
命名方式强烈推荐!
Reducer的分离与合并
随着项目功能变得越来越复杂,需要 Redux 管理的状态也会越来越多
此时,有两种方式来处理状态的更新:
- 使用一个 reducer:处理项目中所有状态的更新
- 使用多个 reducer:按照项目功能划分,每个功能使用一个 reducer 来处理该功能的状态更新
推荐:使用多个 reducer(第二种方案),每个 reducer 处理的状态更单一,职责更明确
此时,项目中会有多个 reducer,但是 store 只能接收一个 reducer,因此,需要将多个 reducer 合并为一根 reducer,才能传递给 store
合并方式:使用 Redux 中的
combineReducers
函数注意:
合并后,Redux 的状态会变为一个对象,对象的结构与 combineReducers 函数的参数结构相同
- 比如,此时 Redux 状态为:
{ a: aReducer 处理的状态, b: bReducer 处理的状态 }
- 比如,此时 Redux 状态为:
1 | import { combineReducers } from 'redux' |
注意:虽然在使用
combineReducers
以后,整个 Redux 应用的状态变为了对象
,但是,对于每个 reducer 来说,每个 reducer 只负责整个状态中的某一个值- 也就是:每个reducer只负责自己要处理的状态
- 举例:
- 登录功能:
loginReducer
处理的状态只应该是跟登录相关的状态- 个人资料:
profileReducer
处理的状态只应该是跟个人资料相关的状态
- 个人资料:
- 登录功能:
- 合并 reducer 后,redux 处理方式:只要合并了 reducer,不管分发什么 action,所有的 reducer 都会执行一次。各个 reducer 在执行的时候,能处理这个 action 就处理,处理不了就直接返回上一次的状态。所以,我们分发的某一个 action 就只能被某一个 reducer 来处理,也就是最终只会修改这个 reducer 要处理的状态,最终的表现就是:分发了 action,只修改了 redux 中这个 action 对应的状态!
redux管理哪些状态
不同状态的处理方式:
- 将所有的状态全部放到 redux 中,由 redux 管理
- 只将某些状态数据放在 redux 中,其他数据可以放在组件中,比如:
- 如果一个状态,只在某个组件中使用(比如,表单项的值),推荐:放在组件中
- 需要放到 redux 中的状态:
- 在多个组件中都要使用的数据【涉及组件通讯】
- 通过 ajax 请求获取到的接口数据【涉及到请求相关逻辑代码放在哪的问题】