RxJS流中使用Immer produce操作对象失败,求解决方案
解决方案
核心问题
你遇到的报错是因为sessionAction.payload是Observable类型,而Immer的produce仅支持处理普通可draft对象(如纯对象、数组),所以必须先提取出Observable内部的实际数据值。
具体解决方法
1. 在switchMap中嵌套处理payload的Observable
如果sessionAction.payload本身就是Observable,需要在外部流中先订阅这个内部Observable,拿到它发射的实际数据后再调用Immer:
import { switchMap, of } from 'rxjs'; import { produce } from 'immer'; // 假设yourMergedAction$是你合并后的Action流 yourMergedAction$.pipe( switchMap(sessionAction => // 先订阅payload这个Observable,获取实际值 sessionAction.payload.pipe( switchMap(payloadValue => { // 这里payloadValue就是普通对象,可直接传给produce const updatedState = produce(yourCurrentState, draft => { draft.session = payloadValue; // 示例修改逻辑 }); return of(updatedState); // 返回新状态的Observable }) ) ) );
2. 检查Action创建逻辑
排查你创建Action的代码,是否误将Observable作为payload传入。正常的Action payload应该是普通数据:
// ❌ 错误:payload是Observable const badAction = { type: 'SESSION_UPDATED', payload: fetchSessionData() }; // ✅ 正确:payload是普通对象/数据 fetchSessionData().subscribe(data => { const goodAction = { type: 'SESSION_UPDATED', payload: data }; });
3. 利用state-adapt内置的Immer支持
state-adapt本身集成了Immer,无需手动调用produce。你可以直接在状态适配器的handler中编写Immer风格的修改逻辑,框架会自动处理payload:
import { adapt } from '@state-adapt/rxjs'; const sessionAdapter = adapt({ initialState: { userId: '', token: '' }, handlers: { // 这里的payload已经是普通对象,直接修改状态即可 UPDATE_SESSION: (state, payload) => { state.userId = payload.userId; state.token = payload.token; } } }); // 将你的Action流传入适配器 sessionAdapter.actions(yourMergedAction$);
内容的提问来源于stack exchange,提问作者J King
相关产品推荐
相关产品推荐

