NextJs搭配Chakra-UI报useId/useSyncExternalStore非函数错误
问题描述
在Next.js项目中使用Chakra Provider时持续触发报错,尝试将React版本升级至17、18均未解决问题,目前共出现两类同根因报错:
- 第一类:
TypeError: React__namespace.useSyncExternalStore is not a function - 第二类:服务端渲染阶段触发的报错,具体信息如下:
Server Error TypeError: React__namespace.useId is not a function This error happened while generating the page. Any console logs will be displayed in the terminal window. Source pages/_document.js (8:31) @ Function.getInitialProps 6 | class MyDocument extends Document { 7 | static async getInitialProps(ctx) { > 8 | const initialProps = await Document.getInitialProps(ctx); | ^ 9 | return { ...initialProps }; 10 | } 11 |
该
useId报错在页面生成阶段触发,所有控制台日志会输出在终端窗口,错误定位到pages/_document.js文件第8行第31列的getInitialProps方法位置。
根因
两个报错都是React运行时版本不匹配、或者Chakra Provider挂载位置错误导致的:
useId、useSyncExternalStore是React 18正式版才内置的Hook,只要运行时加载的React版本低于18.0.0,就会报“不是一个函数”的错误。很多时候就算手动改了package.json里的React版本,锁文件残留、多版本React共存都会导致实际运行时还是加载旧版本。- Chakra UI v2+本身要求React >=18、Next.js >=12.1.7,版本不满足要求也会触发报错。
- 最容易踩的坑是把Chakra Provider写在
_document.js里——_document.js运行在Next.js服务端的特殊渲染上下文,本身不支持调用React Hook,在这里挂载依赖Hook的Provider必然报错。
修复方案
按以下顺序操作即可解决:
- 清理依赖缓存,统一版本
先删除项目下的node_modules目录,以及对应包管理器的锁文件(npm删package-lock.json,yarn删yarn.lock,pnpm删pnpm-lock.yaml)。
打开package.json,把相关依赖版本调整到符合要求的范围:
重新执行安装命令装依赖,装完后跑{ "dependencies": { "next": ">=12.1.7", "react": ">=18.2.0", "react-dom": ">=18.2.0", "@chakra-ui/react": ">=2.0.0", "@emotion/react": ">=11.0.0", "@emotion/styled": ">=11.0.0", "framer-motion": ">=10.0.0" } }npm ls react(其他包管理器对应执行yarn list react、pnpm list react),如果输出里存在多个React版本,通过package.json的resolutions字段强制全项目使用同一个React 18版本即可。 - 修正Chakra Provider挂载位置
不要在pages/_document.js里引入、挂载Chakra Provider,所有全局Provider都要写到pages/_app.js里:// pages/_app.js import { ChakraProvider } from '@chakra-ui/react' // 引入你自定义的Chakra主题,没有自定义主题可以去掉theme参数 import customTheme from '../theme' export default function MyApp({ Component, pageProps }) { return ( <ChakraProvider theme={customTheme}> <Component {...pageProps} /> </ChakraProvider> ) }_document.js只保留默认的文档结构代码即可,不要放任何业务组件、全局Provider。 - 重启开发服务
重新跑npm run dev启动项目,两个报错都会消失。
内容的提问来源于stack exchange,提问作者Chinmay Gopal
相关产品推荐
相关产品推荐

