如何修复Preact组件在Unistore多setState操作时不重新渲染的问题?
解决Preact+Unistore中isLoading状态不触发渲染的问题
你遇到的这个问题其实很常见,核心原因是两次状态更新被批量合并了,导致组件永远看不到isLoading: true的中间状态,直接渲染了最终的isLoading: false。
为什么会这样?
- 同步数据请求的情况:如果你的
Api.get是同步返回结果(比如本地模拟数据直接用Promise.resolve返回),那两个store.setState会在同一个同步代码块里执行。Preact/Unistore会合并这两次状态更新,isLoading: true会被后面的isLoading: false直接覆盖,组件根本没机会渲染loading状态。 - 异步请求但批量更新:即使
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
相关产品推荐
相关产品推荐

