Redux
JS应用的状态容器,提供可预测的状态管理。 能够实现集中式状态管理
Redux是使用action事件来管理和更新应用状态的模式和工具库。
该状态库以集中式Store(centralized store)的方式对整个应用中使用的状态进行集中管理,其规则确保状态只能以可预测的方式更新。
redux状态库和react没有任何关系,即可以在其他库或原生开发中也使用redux来实现状态管理。
概念
store
是一个容器,由于保存整个应用中要管理状态的各项功能
state
是整个应用中各组件间需要共享访问的数据
action
是一个普通的对象,用于描述发生了什么,这个对象通常有`type`和`payload`这两个属性
action creator
这是action创建函数,主要用于创建生成action对象,以实现对action对象的复用
reducer
这是一个纯函数,用于同步更新状态数据 reducer函数接收旧的state和action作为参数,返回新的state数据。
函数签名:(state,action) => newState
React 必需符合以下规则:
- 仅使用
state和action参数计算新的状态值- 禁止直接修改
state。必须通过复制现有的state并对复制的值进行更改的方式来做不可变更新(immutable updates).- 禁止任何异步逻辑,依据随机值或导致其他"副作用"的代码
reducer函数内部的逻辑通常遵循以下步骤:
- 检查reducer是否关心这个action
- 如果是,则复制state,使用新值更新state副本,然后返回新state
- 否则,返回原来的state不变 即通常在reducer函数体内部,使用switch-case语法来实现逻辑处理
dispatch
dispatch(action)
更新state的唯一方法是调用store.dispatch()并传入一个action对象
注意:在redux使用时,也是不能直接调用reducer()函数来更新状态数据,而是需要store.dispatch(action)来触发调用reducer()更新状态数据。
Selector
是一个函数组件的hook,useSelector,Selector函数可以从store状态树中提取指定的片段
使用
npm i redux //安装
定义reducer函数
通常在`./src/reducers目录中创建reducer函数模块:`
//使用rxreducer在vscode中快速生成
import { DECREMENT, INCREMENT } from "../actions/action-types"
/**
* 初始状态数据
*/
const initialState = {
count: 0, // 计数数量
}
/**
* reducer 纯函数,作用:用于同步更新状态数据
* @param {*} state 旧的状态数据
* @param {*} action action对象,通常有 { type, payload } 属性
* @returns
*/
const counterReducer = (state = initialState, { type, payload }) => {
// 将 state 进行深复制(深克隆)
const copyState = JSON.parse(JSON.stringify(state))
// 根据 action.type 判断进行何种更新处理
switch (type) {
case INCREMENT: // 计数数量加
copyState.count += payload.num
return copyState // 返回新的状态数据
case DECREMENT: // 计数数量减
copyState.count -= payload.num
return copyState
default:
return state
}
}
export default counterReducer
定义多个独立到的reducer后,要将各独立reducer合并为一个根reducer(相当于vue中的模块)
import { combineReducers } from 'redux'
import counterReducer from './counter'
import userReducer from './user'
// 将多个独立的 reducer 合并为一个根 reducer
const rootReducer = combineReducers({
counter: counterReducer,
user: userReducer,
})
export default rootReducer
定义action creator函数
通常在`./src/actions`目录下创建:
import { DECREMENT, INCREMENT } from "./action-types";
/**
* action creator函数,用于生成 action 对象
* 加数量的 action 创建函数
*/
export const incrementActionCreator = num => ({
type: INCREMENT,
payload: {
num,
},
})
创建Store
通常在`./src/store`目录中处理:
import { createStore } from 'redux'
import rootReducer from '../reducers'
// 创建 Store 仓库
const store = createStore(rootReducer)
export default store
基于根reducer去创建Store仓库
在react中使用redux
redux与react没有任何关系,想在react中使用需安装一个绑定库:
npm i react-redux // 安装绑定库
将react与redux绑定
在src的入口index.js文件中导入:
// React 18.x 写法
import ReactDOM from 'react-dom/client'
import { Provider } from 'react-redux'
import store from './store'
import App from './App'
// 创建 root 根
const root = ReactDOM.createRoot(document.getElementById('root'))
// 在 root 根下挂载节点
root.render(
<Provider store={store}>
<App />
</Provider>
)
引入react-redux包中的Provider组件(这个组件相当于是对Context中Provider的封装)和已定义好的redux中的store模块。
将App组件的渲染包裹在Provider组件渲染内部。
Provider组件的store属性保存需要在整个应用中全局共享的redux的store仓库。
在组件中链接store进行使用
要调用react-redux中的connect()函数组件中链接redux的store,connect()的两个参数主要用于将store中的state与dispatch()向组件的props属性注入,以便在包裹组件内部可以使用到store中的数据。
注意:connec()的返回值是一个HOC的函数
三大原则
单一数据源
整个应用的state被存储在object tree中,并且这个object tree只存在于唯一一个store中。
State是只读的
唯一改变state的方法就是触发action,action是一个用于描述已发生事件的普通对象。
使用纯函数来执行修改
为了描述action如何改变state tree ,你需要编写reducers。
异步Action
action creator
要将同步action创建函数与异步任务(比如网络请求)结合起来,标准的做法是使用redux thunk 中间件。 需要安装redux-thunk这个专门的库。
通过使用指定的middleware,action创建函数除了返回action对象外还可以返回函数。
绑定库中的hooks
在react-redux绑定库中,可使用如下hooks实现功能:
useStore()-获取redux中store对象的引用useDispatch()- 获取redux中store的dispatch API 方法引用useSelect()-从redux的store中挑选应用中要使用到的state状态数据片段
immutable
不可变更新所使用的库
在reducer()函数内部,如果使用深克隆对state状态数据进行克隆处理,性能开销可能会大增,facebook提出immutable-js库,这个库有更好的性能表现,可以使用immutable-js来实现reducer中state的处理。