pro-components: 🐛[BUG]ProLayout does not work with React 18

提问前先看看:

https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md

🐛 bug 描述

升级到React 18后, ProLayout无法渲染,查看浏览器里面的日志,出现很多错误: index.mjs:634 Uncaught TypeError: Cannot read properties of undefined (reading ‘0’) at useSWRHandler (index.mjs:634:1) at useSWRArgs (index.mjs:612:1) at BaseProLayout (ProLayout.js:201:1) at renderWithHooks (react-dom.development.js:16305:1) at updateFunctionComponent (react-dom.development.js:19588:1) at beginWork (react-dom.development.js:21601:1) at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1) at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1) at invokeGuardedCallback (react-dom.development.js:4277:1) at beginWork$1 (react-dom.development.js:27451:1) useSWRHandler @ index.mjs:634 useSWRArgs @ index.mjs:612 BaseProLayout @ ProLayout.js:201 renderWithHooks @ react-dom.development.js:16305 updateFunctionComponent @ react-dom.development.js:19588 beginWork @ react-dom.development.js:21601 callCallback @ react-dom.development.js:4164 invokeGuardedCallbackDev @ react-dom.development.js:4213 invokeGuardedCallback @ react-dom.development.js:4277 beginWork$1 @ react-dom.development.js:27451 performUnitOfWork @ react-dom.development.js:26557 workLoopSync @ react-dom.development.js:26466 renderRootSync @ react-dom.development.js:26434 recoverFromConcurrentError @ react-dom.development.js:25850 performSyncWorkOnRoot @ react-dom.development.js:26096 flushSyncCallbacks @ react-dom.development.js:12042 commitRootImpl @ react-dom.development.js:26959 commitRoot @ react-dom.development.js:26682 finishConcurrentRender @ react-dom.development.js:25981 performConcurrentWorkOnRoot @ react-dom.development.js:25809 workLoop @ scheduler.development.js:266 flushWork @ scheduler.development.js:239 performWorkUntilDeadline @ scheduler.development.js:533 react-dom.development.js:18687 The above error occurred in the <BaseProLayout> component:

at BaseProLayout (http://localhost:3001/static/js/bundle.js:14779:13)
at FormProvider (http://localhost:3001/static/js/bundle.js:88668:31)
at LocaleProvider (http://localhost:3001/static/js/bundle.js:46893:90)
at ProviderChildren (http://localhost:3001/static/js/bundle.js:40521:24)
at LocaleReceiver (http://localhost:3001/static/js/bundle.js:46768:90)
at ConfigProvider (http://localhost:3001/static/js/bundle.js:40624:13)
at div
at SWRConfig$1 (http://localhost:3001/static/js/bundle.js:169152:21)
at ConfigProviderWrap (http://localhost:3001/static/js/bundle.js:20702:24)
at ProviderChildren (http://localhost:3001/static/js/bundle.js:40521:24)
at LocaleReceiver (http://localhost:3001/static/js/bundle.js:46768:90)
at ConfigProvider (http://localhost:3001/static/js/bundle.js:40624:13)
at ProLayout (http://localhost:3001/static/js/bundle.js:15073:28)
at header
at div
at App

经过调试,发现ProLayout.js下面的userState进去了两次,第二次,defaultId=’pro-layout-2’的时候报错。 var _useState = useState(function () { layoutIndex += 1; return “pro-layout-”.concat(layoutIndex); }),

📷 复现步骤

  1. 通过yarn create react-app web-test --template typescript创建一个react项目.
  2. yarn add antd @ant-design/pro-components添加依赖。
  3. 检查react, react-dom版本,均为18.2.0.
  4. 修改App.tsx, 添加最简单的ProLayout。
   function App() {

  return (
    <div className="App">
        <ProLayout id="layout">
          <PageContainer title="测试" />
        </ProLayout>
    </div>
  );
}
  1. 启动项目 yarn start.
  2. 浏览器中打开地址”http://localhost:3000,页面无法显示。
  3. 修改index.tsx代码:
// const root = createRoot(
//     document.getElementById('root') as HTMLElement
// );
//
// root.render(
//     <React.StrictMode>
//       <App />
//     </React.StrictMode>
// );

ReactDOM.render(
    <React.StrictMode>
      <App />
    </React.StrictMode>,
    document.getElementById('root') as HTMLElement);
  1. 错误消失。页面可以正常显示。
  2. 结论:ReactDOM.render在react18中列为将被移除的功能,官方要求改成createRoot的方式。但是createRoot的方式ProLayout无法正常显示。

🏞 期望结果

在createRoot方式下,页面正常显示ProLayout,不出现错误。

💻 复现代码

index.tsx

// 不能正常显示的代码
// const root = createRoot(
//     document.getElementById('root') as HTMLElement
// );
//
// root.render(
//     <React.StrictMode>
//       <App />
//     </React.StrictMode>
// );

// 可以正常显示的代码
ReactDOM.render(
    <React.StrictMode>
      <App />
    </React.StrictMode>,
    document.getElementById('root') as HTMLElement);

app.tsx

function App() {

  return (
    <div className="App">
        <ProLayout id="layout">
          <PageContainer title="测试" />
        </ProLayout>
    </div>
  );
}

© 版本信息

  • ProComponents 版本: 2.3.34
  • Antd版本:4.23.3
  • 浏览器环境:Chrome
  • 开发环境 : mac OS

🚑 其他信息

试过其它版本ProComponents:2.3.35, Antd: 5.0.0,同样的问题

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 1
  • Comments: 17 (2 by maintainers)

Most upvoted comments

去掉<React.StrictMode />可以正常渲染, 但是当使用路由跳转时, 会再次报错

同路由跳转报错,有啥解决办法吗

如何组件是以react.lazy导入,那么在prolayout中就必须使用react.suspense包裹outlet组件,不能再prolayout外层使用react.outlet,这样会造成prolayout出现闪烁问题,同时也会造成路由跳转就报错 image

去掉 <React.StrictMode /> 试试

去掉<React.StrictMode />可以正常渲染, 但是当使用路由跳转时, 会再次报错

同路由跳转报错,有啥解决办法吗

如何组件是以react.lazy导入,那么在prolayout中就必须使用react.suspense包裹outlet组件,不能再prolayout外层使用react.outlet,这样会造成prolayout出现闪烁问题,同时也会造成路由跳转就报错 image

试着在Outlet外侧加了Suspense, 解决了 感谢!!!