React 18:如何强制同步渲染?

pie*_*une 7 javascript reactjs react-18

升级到 React 18 后,我遇到了 Leaflet 弹出窗口渲染问题。

看来新的渲染函数已经变成了异步,这破坏了Leaflet弹出窗口的显示(因为Leaflet需要计算弹出窗口的大小来定位,但现在它得到的是空内容,因为React尚未渲染弹出窗口)。

之前(按预期工作):

marker.bindPopup(() => {
  var div = document.createElement('div');
  ReactDOM.render(<MyPopup />);
  console.log(div.innerHTML); // <div>[...]</div>
  return div;
});
Run Code Online (Sandbox Code Playgroud)

使用 React 18(定位损坏):

marker.bindPopup(() => {
  var div = document.createElement('div');
  createRoot(div).render(<MyPopup />);
  console.log(div.innerHTML); // empty string!
  return div;
});
Run Code Online (Sandbox Code Playgroud)

有没有办法强制 React 18 在返回之前渲染弹出窗口div

预先感谢您的帮助和想法

pie*_*une 7

我刚刚找到了另一个似乎有效且更适合生产环境的解决方案:flushSync. 在React文档中,没有提到这个目的,只是选择退出自动批处理。

我仍然不确定这是否是正确的方法,或者它是否会在未来的更新中中断。

marker.bindPopup(() => {
  var div = document.createElement('div');
  const root = createRoot(div);

  flushSync(() => {
    root.render(<MyPopup />);
  });

  console.log(div.innerHTML); // <div>[...]</div>
  return div;
});
Run Code Online (Sandbox Code Playgroud)


小智 0

没有尝试过你的场景,但也许 act 可以工作https://reactjs.org/docs/testing-recipes.html#act

记住导入行为来自react-dom/test-utils

marker.bindPopup(() => {
   var div = document.createElement('div');
   const root = createRoot(div);

   act(() => {
     root.render(<MyPopup />);
   });

   return div;
});
Run Code Online (Sandbox Code Playgroud)