主题
Redux
介绍
Redux 是一个 JavaScript 状态容器,提供可预测化的状态管理。
快速入门
安装
bash
npm i @reduxjs/toolkit@1 react-redux@8@reduxjs/toolkit:内置了很多了工具包,简化 Redux 的使用方式。react-redux:用于链接 React 和 Redux。
示例
项目结构
bash
src
└─ store
├─ modules
│ ├─ counter.js
│ ├─ user.js
│ └─ ...
└─ index.js定义
ts
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { Provider } from 'react-redux'
import store from './store'
import App from './App.tsx'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<Provider store={store}>
<App />
</Provider>
</StrictMode>,
)ts
import { configureStore } from '@reduxjs/toolkit'
import counter from './modules/counter'
const store = configureStore({
reducer: {
counter,
},
})
export type RootState = ReturnType<typeof store.getState>
export type RootDispatch = typeof store.dispatch
export default storets
import { createSlice } from '@reduxjs/toolkit'
import type { RootDispatch } from '../index'
const counterStore = createSlice({
name: 'counter',
// 初始化 state
initialState: {
count: 0,
},
// 同步操作,直接修改
reducers: {
increment(state, action) {
state.count += action.payload
},
decrement(state, action) {
state.count -= action.payload
},
},
})
// 解构出 actionCreator
const { increment, decrement } = counterStore.actions
// 异步操作,返回一个函数
const asyncIncrement = (val: number) => {
return async (dispatch: RootDispatch) => {
setTimeout(() => {
dispatch(increment(val * 100))
}, 3000)
}
}
// 获取 reducer
const reducer = counterStore.reducer
export { increment, decrement, asyncIncrement }
export default reducer使用
tsx
import { useSelector, useDispatch } from 'react-redux'
import type { RootState, RootDispatch } from '../../store'
import { increment, decrement, asyncIncrement } from '../../store/modules/counter'
function ReduxView() {
// 获取 state 中的数据
const { count } = useSelector((state: RootState) => state.counter)
// 获取 dispatch 方法
const dispatch = useDispatch<RootDispatch>()
return (
<>
{/* 调用 dispatch 方法 */}
<button onClick={() => dispatch(increment(2))}>+2</button>
{/* 异步 dispatch */}
<button onClick={() => dispatch(asyncIncrement(2))}>异步 ++</button>
<span>{count}</span>
<button onClick={() => dispatch(decrement(1))}>-1</button>
</>
)
}
export default ReduxViewRedux 的核心思想
为什么需要 Redux?
在构建复杂的前端应用时,常常会遇到这些问题:
- 状态分散:应用的状态(state)分散在各个独立的组件中,难以形成全局视图。
- 数据流混乱:组件层级加深,数据通过 Props 层层传递,或者通过事件随意通信,导致数据流难以追踪和维护。
- 变更不可预测:一个状态可能在任意组件、任意时刻被修改,当出现 bug 时,很难定位是哪个环节导致了错误的状态。
于是 Redux 便诞生了,Redux 并非一个复杂的框架,而是一套状态管理模式,它让状态的变化变得可预测、可追溯。
Redux 的三大原则
- 单一数据源:整个应用的 state 都被存储在一个 store 中的一棵对象树中。
- 状态只读:状态不能直接修改,唯一改变 state 的方法就是触发 action,一个描述发生了什么的对象。
- 变更由纯函数完成:为了描述 action 如何改变 state 树,需要编写 reducers。
什么是 action?
action 本质就是一个普通的 js 对象:
- 必须包含一个 type 字段(通常是字符串),用来描述发生了什么。
- 可以携带一些更新数据所需要的消息,这部分通常被成为 payload。
js
const addTodoAction = {
type: 'ADD_TODO',
payload: {
text: 'Learn Redux',
},
}Zustand 核心特点
- 极简的 API 和模板代码:没有 actions、reducers、dispatch 等概念,所有逻辑都封装在 create 函数中,上手极快。
- 无需 Provider:状态是全局的,不依赖于 React Context。无需在根组件通过
<Provider>包裹组件,可随时地调用。 - 基于 Selector 的性能优化:组件通过
selector函数订阅状态的一部分。只有被订阅的状态变化时,组件才会被重新渲染,天然避免了不必要的渲染。 - 灵活性高:支持集成中间件,可轻松集成 Redux DevTools、日志、持久化存储等功能。
