Redux
Redux 状态更新流程可以概括为一个单向数据流 (one-way data flow),主要分为 5 个关键步骤:
🧭 一图概览
UI 组件 -> dispatch(action) -> reducer -> new state -> store 通知订阅者 -> UI 重新渲染💡 流程详细说明
① 用户触发 Action
当用户在界面上执行操作(比如点击按钮、输入文本等), 组件通过 dispatch() 方法发送一个 action 对象:
js
dispatch({ type: 'INCREMENT' })Action 是一个普通的 JavaScript 对象,至少包含一个 type 属性,用来描述发生了什么。
② Store 接收到 Action
Redux 的 store 是应用状态的唯一来源。 当调用 store.dispatch(action) 时,store 会把这个 action 交给 reducer 来处理。
③ Reducer 处理状态更新
Reducer 是一个纯函数,根据当前 state 和传入的 action,返回一个新的状态:
js
function counterReducer(state = { count: 0 }, action) {
switch (action.type) {
case 'INCREMENT':
return { count: state.count + 1 }
case 'DECREMENT':
return { count: state.count - 1 }
default:
return state
}
}⚠️ 重要:Reducer 不能直接修改原 state,必须返回一个新对象(不可变性原则)。
④ Store 更新并保存新状态
Reducer 返回的新 state 会替换掉旧 state, Redux 内部会存储这个新状态,并触发通知。
⑤ 订阅者 (UI 层) 被通知
所有通过 store.subscribe() 注册的监听函数(例如 React 组件中的 useSelector) 都会被调用,从 store 获取最新的 state,然后触发 UI 重新渲染。
例如,在 React 中:
jsx
const count = useSelector(state => state.count)当 store 的状态改变时,这个组件会自动重新渲染以反映最新数据。
🧩 可视化理解
用户操作
↓
dispatch(action)
↓
reducer(state, action)
↓
返回新 state
↓
store 更新
↓
UI 重新渲染redux 创建reducer
js
// store.js
import { createStore } from 'redux'
// 1. 定义初始状态
const initialState = {
count: 0
}
// 2. 定义 reducer (纯函数)
function counterReducer(state = initialState, action) {
switch (action.type) {
case 'INCREMENT':
return { count: state.count + 1 }
case 'DECREMENT':
return { count: state.count - 1 }
default:
return state
}
}
// 3. 创建 store
const store = createStore(counterReducer)
// 导出 store
export default storeredux-tooltik 创建reducer
🚀 createAsyncThunk
createAsyncThunk 是 Redux Toolkit 提供的一个用于处理异步逻辑的工具。它能够自动生成代表异步请求生命周期的 Action Types,并根据 Promise 的状态触发相应的 Action。
1. 基本语法
js
const actionCreator = createAsyncThunk(typePrefix, payloadCreator)typePrefix: 字符串,用于生成 Action 类型的标识符(如home/fetchHomeData)。生成的三个类型的 Action 分别是:typePrefix/pending: 请求开始。typePrefix/fulfilled: 请求成功(Promise 已解决)。typePrefix/rejected: 请求失败(Promise 已拒绝)。
payloadCreator: 异步回调函数,返回一个 Promise(或使用async/await)。它接收两个参数:arg: 调用该 action 时传递的参数(payload)。thunkAPI: 一个包含dispatch,getState,rejectWithValue等工具的对象。
2. 处理异步数据的两种方式
- 直接在 Payload Creator 中 dispatch (如本例):在回调函数中手动调用其他 action 来更新状态。适用于一个请求需要触发布局多个 reducer 的场景。
- 通过
extraReducers(官方推荐):在createSlice中使用extraReducers监听生成的pending/fulfilled/rejected状态。这种方式更加清晰,逻辑更内聚。
js
import { createSlice , createAsyncThunk } from '@reduxjs/toolkit'
import { getDiscount, getGoodPrice, getHighScore, getHomeHotRecommendData, getHomeLongforData } from '@/services/modules/home';
export const fetchHomeData = createAsyncThunk('goodPriceData', (payload,{dispatch,getState})=>{
getGoodPrice().then(res=>{
dispatch(goodPriceAction(res))
})
getHighScore().then(res=>{
dispatch(highscoreAction(res))
})
getDiscount().then(res=>{
dispatch(discountAction(res))
})
getHomeHotRecommendData().then(res=>{
dispatch(HotRecommendAction(res))
})
getHomeLongforData().then(res=>{
console.log(res);
dispatch(longForAction(res))
})
})
const homeSlice = createSlice({
name: "home",
initialState: {
goodPrice:{},
highScore:{},
disCount:{},
hotRecommend:{},
longFor:{}
},
reducers: {
goodPriceAction(state,{payload}){
state.goodPrice = payload
},
highscoreAction(state,{payload}){
state.highScore = payload
},
discountAction(state,{payload}){
state.disCount = payload
},
HotRecommendAction(state,{payload}){
state.hotRecommend = payload
},
longForAction(state,{payload}){
state.longFor = payload
}
},
})
export const {goodPriceAction,highscoreAction,discountAction,HotRecommendAction,longForAction} = homeSlice.actions
export default homeSlice.reducer案例
https://github.com/dargon-start/lz-airbnd/tree/main/src/store
