外观
Redux 的数据怎么流动?
Store 保存状态。界面派发 action,reducer 根据当前状态和 action 算出下一个状态,订阅者再渲染。Reducer 是纯函数,副作用放在 action 创建函数或中间件里。
原理
一个 action 是带 type 的普通对象,payload 放这次变化的数据。Reducer 不改入参,返回新对象。combineReducers 把大状态拆成几块。
中间件包在 dispatch 外面,可以拦截 action。异步用 thunk:派发一个函数,这个函数拿到 dispatch 和 getState。日志、崩溃上报也可以是中间件。中间件的形式是 store => next => action => {},next 把 action 交给下一层。
React 里用 useSelector 选出需要的字段,用 useDispatch 派发。选择器返回新对象时,默认比较会认为变了,组件就会渲染。选出原始值,或给比较函数。
服务端缓存不是 Redux 的强项。请求的加载、失效和重试用专门的请求库,Redux 里留界面状态。见 状态管理。
新项目如果状态简单,用组件状态或更轻的库即可。Redux 的价值是更新路径固定、中间件和时间旅行调试,适合状态交叉很多的客户端。
追问
为什么 reducer 不能请求接口?
它要可预测、可重复。同一次 action 再放进 reducer 应得到同一个状态。请求在 thunk 或监听器里做完,再派发成功或失败的 action。
和 Context 的差别?
Context 广播一份值,所有消费者跟着渲染。Redux 的选择器让组件只订阅自己用到的那一块。低频的主题用 Context 就够。
易错点
- 在 reducer 里改原 state 的数组再返回它,订阅者看不出变化。
- 把整个 store 都
useSelector(state => state),任何变化都重新渲染。 - action 类型用魔法字符串又没有集中管理,拼写错误变成静默的默认分支。