【发布时间】:2020-11-30 23:26:39
【问题描述】:
我正在考虑实现一个加载屏幕来检查是否加载了所有组件,但遇到了这种奇怪的模式。使用下面的代码,我在控制台中得到 App false 来启动,在 delayHTML 函数返回数据的 2000 毫秒后,我得到 LoadComponent mount event 和 App true。
但随后它又回到了 suspense fallback,我又得到了 2000 毫秒,LoadComponent mount event 和 App true 消息再次出现,看起来像是第二次渲染。我怎样才能避免这种情况?
function App() {
const [fullLoadState, setfullLoadState] = useState(false);
console.log("App " + fullLoadState)
eventBus.on("FullyLoaded", (data) => setfullLoadState(true));
return (
<div>
<Suspense fallback='Fallback'>
<LoadComponent resource={delayHTML(2000)}/>
</Suspense>
<p>{fullLoadState ? null : "Site not fully loaded" }</p>
</div>
);
}
function LoadComponent({resource}){
useEffect(()=> {
console.log ('LoadComponent mount event')
eventBus.dispatch("FullyLoaded", {messsage: 'some message'});
})
const html = resource.read();
return html;
}
export default App;
EventBus 只是 EventListener。 delayHTML 会挂起,直到达到 2000 毫秒才返回一个文本值。
【问题讨论】:
-
两条消息都是预期的行为。更改状态会导致组件(App)重新渲染。
useEffectw/o 依赖也运行在每个渲染上。 -
另外你不应该在渲染中执行副作用(比如订阅)。使用适当的清理功能将此代码移动到
useEffect。eventBus.on("FullyLoaded", (data) => setfullLoadState(true));