我有一个罕见的用例,我需要在我的 React 组件中注册多个根,并在组件卸载时销毁它们。显然,我在渲染时卸载了根。我通过调用模拟了这种情况root.unmount()
就在之后root.render(...)
。在以下示例中:https://codesandbox.io/s/eager-grothendieck-h49eoo?file=%2Fsrc%2FApp.tsx https://codesandbox.io/s/eager-grothendieck-h49eoo?file=%2Fsrc%2FApp.tsx
这会导致以下警告:Warning: Attempted to synchronously unmount a root while React was already rendering. React cannot finish unmounting the root until the current render has completed, which may lead to a race condition.
这个警告对我来说意味着有一种异步方法可以卸载根目录,但我无法找到如何卸载根目录的方法。包装root.unmount()
在异步函数中(const unmount = async () => root.unmount()
) 不工作。有任何想法吗?我在这里得到完全错误的东西吗?
在我们的项目中,我们通过以下方式异步卸载setTimeout
。我创建了一个更新的codesandbox,你可以找到工作示例here https://codesandbox.io/s/cranky-engelbart-9zl1xf?file=/src/App.tsx.
下面的代码片段显示了如何处理安装和卸载。请注意,安装和卸载通过以下方式与同步渲染循环分离:setTimeout
,这是为了避免同步挂载和异步卸载之间的竞争。否则,可能会发生该组件在从先前的渲染中安装后立即被卸载的情况。
我不相信这是最好的解决方案,但到目前为止它对我们有效。
function MyComponent() {
const containerRef = useRef<HTMLDivElement | null>(null);
const rootRef = useRef<ReactDOM.Root>();
useEffect(() => {
const renderTimeout = setTimeout(() => {
if (containerRef.current) {
console.log("create root");
rootRef.current =
rootRef.current ?? ReactDOM.createRoot(containerRef.current);
}
if (containerRef.current && rootRef.current) {
console.log("component render");
rootRef.current.render(<div>mounted component</div>);
}
});
return () => {
clearTimeout(renderTimeout);
console.log("unmount");
const root = rootRef.current;
rootRef.current = undefined;
setTimeout(() => {
console.log("component unmount");
root?.unmount();
});
};
}, [rootRef]);
return <div ref={containerRef}></div>;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)