MVI架构中异步数据更新后UI没变化怎么办?

艳花的笔记 阅读 43

我在React项目里尝试用MVI模式实现数据加载功能,但发现当异步请求完成后,UI界面始终显示初始状态。我已经按规范写了Effect和ViewModel,但页面还是没更新,哪里出错了呢?


// ViewModel处理加载数据的action
handleEvent(event) {
  if (event.type === 'LOAD_DATA') {
    return this.effect$
      .fromPromise(fetchData())
      .map(data => ({ type: 'DATA_LOADED', payload: data }))
      // 这里是不是漏了什么步骤?
  }
}

// 在View中订阅了viewModel的state
const App = () => {
  const state = useViewModel(AppVM).state;
  return <div>{state.isLoading ? '加载中' : state.data}</div>;
};

我已经确认网络请求成功返回了数据,viewModel的effect也触发了,但UI始终显示初始的isLoading状态。尝试过手动调用viewModel.updateModel()但文档说不该这么做,有没有其他解决办法?

我来解答 赞 2 收藏
二维码
手机扫码查看
1 条解答
皇甫雨路
MVI架构里UI不更新,大概率是State没触发更新。你这段代码里确实少了一个关键步骤:Effect没有被Dispatch。你在ViewModel里写了Effect处理,但最后要记得把Effect发射出去,否则State不会变。

修改handleEvent方法,加一行dispatch:

handleEvent(event) {
if (event.type === 'LOAD_DATA') {
this.dispatch({ type: 'LOADING_START' }); // 也可以直接改state
return this.effect$
.fromPromise(fetchData())
.map(data => {
this.dispatch({ type: 'DATA_LOADED', payload: data });
return { type: 'DATA_LOADED', payload: data };
})
}
}

或者你也可以用reduce来更新State:

reduce(state, event) {
switch(event.type) {
case 'DATA_LOADED':
return { ...state, data: event.payload, isLoading: false };
default:
return state;
}
}

React里用useViewModel的话,确保你监听的是正确的state字段。你检查一下viewModel.state的isLoading和data有没有正确变化。有时候容易监听错字段,或者用了不可变对象没更新引用。

如果你用的是基于类的ViewModel,也可以手动触发一次update:

this.viewModel.updateModel({
data: newData,
isLoading: false
});

不过这个方式不如前面几种标准。

MVI模式里,Effect触发后一定要通过dispatch发一个Event,再通过reduce去更新State,这样View才能感知到变化。你当前的代码只返回了Event,但没dispatch出去,所以State一直是初始值。
点赞 4
2026-02-05 23:01