Umi中useModel获取的状态修改后组件没有重新渲染怎么办?

梓怡(打工版) 阅读 10

在Umi项目里用useModel获取模型状态,修改了状态值后页面没更新,控制台也没有报错。比如这个页面:


<template>
  <div>
    <p>当前计数:{{ count }}</p>
    <button @click="increment">+1</button>
  </div>
</template>

<script>
import { useModel } from 'umi';

const Demo = () => {
  const count = useModel('counter', (model) => model.count);
  const increment = () => {
    useModel('counter').increment(); // 调用model方法
  };
  return { count, increment };
};
export default Demo;
</script>

我尝试过在increment方法里直接赋值count = count + 1,也试过用Vue.set,但都没效果。检查model定义时发现counter模型是用defineModel导出的,初始值是0。是不是需要什么特别的响应式处理?

我来解答 赞 3 收藏
二维码
手机扫码查看
1 条解答
UP主~慧丽
这个问题的关键在于你用了两次 useModel,这会导致响应式失效。我的做法是只调用一次 useModel,把整个模型解构出来使用。

具体来说,你的代码应该改成这样:


import { useModel } from 'umi';

const Demo = () => {
const { count, increment } = useModel('counter'); // 只调用一次useModel
return (
<div>
<p>当前计数:{count}</p>
<button onClick={increment}>+1</button>
</div>
);
};
export default Demo;


这里有几个需要注意的地方:第一,useModel只需要调用一次,直接解构出你需要的值和方法;第二,确保你的 counter 模型里定义的 increment 方法是通过 setState 或者 immer 来更新状态的。

我之前也踩过类似的坑,当时就是因为在同一个组件里多次调用 useModel,导致响应式断开了。Umi 的 model 系统其实已经帮你处理好响应式了,按照上面的方式改就没问题了。

对了,记得检查下你的 counter 模型是不是类似这样的结构:


export default defineModel({
state: {
count: 0,
},
reducers: {
increment(state) {
state.count += 1; // immer 会自动处理不可变数据
},
},
});


这样做既简单又符合 Umi 的最佳实践。如果还有问题可以再交流,咱们一起琢磨。
点赞 1
2026-02-15 17:09