You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复Preact组件在Unistore多setState操作时不重新渲染的问题?

解决Preact+Unistore中isLoading状态不触发渲染的问题

你遇到的这个问题其实很常见,核心原因是两次状态更新被批量合并了,导致组件永远看不到isLoading: true的中间状态,直接渲染了最终的isLoading: false。

为什么会这样?

  1. 同步数据请求的情况:如果你的Api.get是同步返回结果(比如本地模拟数据直接用Promise.resolve返回),那两个store.setState会在同一个同步代码块里执行。Preact/Unistore会合并这两次状态更新,isLoading: true会被后面的isLoading: false直接覆盖,组件根本没机会渲染loading状态。
  2. 异步请求但批量更新:即使Api.get是异步的,Preact的默认批量更新机制也可能延迟第一个状态的渲染,直到第二个更新完成后才一起触发组件重绘。

具体解决方案

方案1:确保数据请求是真正的异步操作

如果是模拟的API请求,给它加个延迟,让它成为真正的异步任务:

// 修改你的Api实现,模拟网络延迟
const Api = {
  get(url) {
    return new Promise(resolve => {
      setTimeout(() => {
        resolve({ data: /* 你的任务数据 */ });
      }, 100); // 100ms延迟,足够让loading状态渲染出来
    });
  }
};

方案2:手动拆分状态更新时机

如果不想修改API,可以在设置isLoading: true后,让浏览器先完成渲染再执行数据请求:

// 更新actions.js中的getJobs方法
async getJobs() {
  store.setState({ isLoading: true });
  // 等待浏览器下一次重绘后再请求数据
  await new Promise(resolve => requestAnimationFrame(resolve));
  const { data } = await Api.get(`/jobs`);
  store.setState({ jobs: data, isLoading: false });
}

requestAnimationFrame会确保isLoading: true的状态已经触发组件渲染,再去执行数据请求,这样loading文本就能正常显示了。

方案3:禁用批量更新(不推荐)

如果是Preact的批量更新机制导致的,也可以用它提供的不稳定API手动控制,但这个API可能在未来版本变动,谨慎使用:

import { unstable_batchedUpdates } from 'preact';

async getJobs() {
  // 第一个更新不批量,立即触发渲染
  store.setState({ isLoading: true });
  const { data } = await Api.get(`/jobs`);
  // 批量处理第二个更新
  unstable_batchedUpdates(() => {
    store.setState({ jobs: data, isLoading: false });
  });
}

验证效果

修改后重新运行,你会发现组件会先显示"loading...",等待数据加载完成后再渲染任务列表,符合你的预期。

内容的提问来源于stack exchange,提问作者iwgx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:52:57