研究了 redux 一周了,做个总结
Redux 是 JavaScript 应用的状态容器,提供可预测的状态管理。
安装 Redux
之前的教程都在手动写 Action 来触发 reducer, 在最新文档官方建议装个 Redux Toolkit
,RTK 包含了有助于简化许多常见场景的工具,包括 配置 Store, 创建 reducer 并编写 immutable 更新逻辑, 甚至还包含 一次性创建整个 State 的 “切面”。让我们的代码向优雅更进一步!
文档地址:安装 | Redux 中文官网
基本概念
Redux 是一个管理全局应用状态的库
Redux 使用 "单向数据流"
-
UI 根据 state 显示 HTML 文档流
-
用户触发更新事件,通过 Redux 创建 Action
-
Action 是有
type
字段的纯对象,描述发生了什么 -
通过
type
字段,触发相应的 Reducer -
Reducer 是纯函数,基于先前的 state 和 action 来计算新的 state
-
state 改变,触发组件更新
一个数据流就循环起来了,每个操作只做自己分内的事,保证数据单向流动。
常用 API
总结一下文档上给的示例程序用到的 API,感觉用这些就足够了呀。
useSelector : (选择器)
快速地找出全局 state 中的数据
// 拎出 posts
useSelector(state => {
// state 是全局 state
return state.posts
})
// 查询某条 posts
const findPostById = (state, id) => {
return state.posts.find(post => post.id === id)
}
useSelector(state => findPostById(state, id))
更推荐的方式是把 useSelector 的函数统一管理起来,以后修改数据结构一改全改了,方便管理。
createSlice : (创建 store 切片)
方便地创建一个 store 切片,看过之前的代码创建 store 的肯定知道这句话的分量。
import { createSlice } from '@reduxjs/toolkit'
const initialState = [
{ id: '1', title: 'First Post!', content: 'Hello!' },
{ id: '2', title: 'Second Post', content: 'More text' }
]
const postsSlice = createSlice({
name: 'posts',
initialState,
reducers: {
// 普通写法
reactionAdd(state, action) {
const { postId, emoji: emojiName } = action.payload
const post = state.find((post) => post.id === postId)
post.reactions[emojiName]++
},
// 可以在执行 reducer 之前处理下数据
postAdd: {
reducer(state, action) {
state.push(action.payload)
},
prepare(title, content, userId) {
return {
payload: {
id: nanoid(),
title,
content,
},
}
},
}
}
})
export default postsSlice.reducer
Redux 官方文档推荐不要将需要计算的逻辑写在业务代码里,应尽量抽到 redux 里做。
如果 action 需要包含唯一 ID 或其他一些随机值,请始终先生成该随机值并将其放入 action 对象中。 Reducer 中永远不应该计算随机值,因为这会使结果不可预测。
useDispatch : ( dispatch action )
分发 action。这是触发 state 变化的惟一途径。
用法:
const onSavePostClicked = () => {
if (title && content) {
dispatch(postAdded(title, content))
}
}
详细文档:Store | Redux 中文官网
createAsyncThunk
通常一个请求有这么几个过程:pending | fulfilled | reject
通过生成 action type 和 action creator 并生成一个自动 dispatch 这些 action 的 thunk。您提供一个回调函数来进行异步调用,并把结果数据返回成 Promise。