升级至Next.js 12后React-Dom组件类型无效错误的排查求助
问题:Next.js 10 升级至 12 后出现 React 组件类型错误
升级大型项目到 Next.js 12 后,出现以下错误:
app_container | Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. app_container | at renderElement (/app/node_modules/react-dom/cjs/react-dom-server.browser.development.js:6043:9) app_container | at renderNodeDestructiveImpl (/app/node_modules/react-dom/cjs/react-dom-server.browser.development.js:6104:11) app_container | at renderNodeDestructive (/app/node_modules/react-dom/cjs/react-dom-server.browser.development.js:6076:14) app_container | at renderForwardRef (/app/node_modules/react-dom/cjs/react-dom-server.browser.development.js:5859:5) app_container | at renderElement (/app/node_modules/react-dom/cjs/react-dom-server.browser.development.js:6005:11) app_container | at renderNodeDestructiveImpl (/app/node_modules/react-dom/cjs/react-dom-server.browser.development.js:6104:11) app_container | at renderNodeDestructive (/app/node_modules/react-dom/cjs/react-dom-server.browser.development.js:6076:14) app_container | at renderNode (/app/node_modules/react-dom/cjs/react-dom-server.browser.development.js:6259:12) app_container | at renderHostElement (/app/node_modules/react-dom/cjs/react-dom-server.browser.development.js:5642:3) app_container | at renderElement (/app/node_modules/react-dom/cjs/react-dom-server.browser.development.js:5952:5)
无法准确定位错误位置,项目代码量大难以找到根源。已知这类错误常和导入时的对象解构有关,但不知道怎么定位具体位置。
附上 package.json 片段:
{ ... "scripts": { "dev": "yarn && TSC_NONPOLLING_WATCHER=1 NODE_ENV=development nodemon", "generate": "graphql-codegen", "build": "next build && tsc --project tsconfig.server.json", "start": "NODE_ENV=production node dist/server.js", "build:preprod": "PORT=3332 next build && tsc --project tsconfig.server.json", "start:preprod": "PORT=3332 NODE_ENV=production node dist/server.js", "lint": "eslint --ext .tsx --ext .ts .", "clean": "npx rimraf node_modules && npx rimraf .next" }, "dependencies": { "@apollo/client": "^3.7.15", "@apollo/react-common": "^3.1.4", "@apollo/react-components": "^4.0.0", "@apollo/react-hoc": "^4.0.0", "@apollo/react-hooks": "^4.0.0", "@codemirror/basic-setup": "^0.18.2", "@codemirror/commands": "^0.18.3", "@codemirror/gutter": "^0.18.4", "@codemirror/lang-javascript": "^0.18.0", "@codemirror/lang-markdown": "^0.18.4", "@codemirror/state": "^0.18.7", "@codemirror/theme-one-dark": "^0.18.1", "@codemirror/view": "^0.18.17", "@graphql-codegen/cli": "^2.2.0", "@graphql-codegen/introspection": "^2.1.1", "@graphql-codegen/typescript": "^2.2.2", "@graphql-codegen/typescript-operations": "^2.1.4", "@graphql-codegen/typescript-react-apollo": "^3.1.4", "@graphql-codegen/typescript-react-query": "^3.5.8", "@svgr/webpack": "^5.5.0", "@types/react": "^17.0.20", "add": "^2.0.6", "apollo-client": "^2.6.10", "babel-plugin-transform-define": "^2.0.1", "core-js": "^3.2.1", "eslint-config-prettier": "^8.3.0", "express": "^4.17.1", "graphql": "^15.0.0", "graphql-tag": "^2.10.1", "lang-papershive": "^0.1.16", "moment": "^2.29.4", "next": "12", "next-fonts": "^1.5.1", "next-plugin-custom-babel-config": "^1.0.5", "next-routes": "^1.4.2", "node-fetch": "^2.6.1", "pdfjs": "^2.4.7", "pdfjs-dist": "2.16.105", "react": "latest", "react-apollo": "^3.1.5", "react-csv": "^2.2.2", "react-device-detect": "^2.2.2", "react-dom": "latest", "react-fast-compare": "^3.2.0", "react-mathjax": "^1.0.1", "react-pdf": "^5.7.2", "react-player": "^2.9.0", "react-querybuilder": "^5.1.1", "react-sortable-hoc": "^2.0.0", "styled-components": "v6.0.0-rc.1", "vue": "3.0.5" }, "devDependencies": { "@types/express": "^4.17.1", "@types/graphql": "^14.2.3", "@types/node": "^17.0.21", "eslint": "7.32.0", "eslint-config-next": "11 ", "nodemon": "^2.0.12", "prettier": "^2.4.0", "regenerator-runtime": "^0.13.3", "ts-loader": "^9.2.3", "ts-node": "^10.9.1", "typescript": "^4.7.4" }, "proxy": "localhost:3001" }
排查方案
一、先处理依赖版本冲突(从你的 package.json 看有明显问题)
- React 版本不匹配:Next.js 12 要求 React 17 或 18,但你用了
latest,同时@types/react是 17.0.20,版本不一致会导致渲染异常。固定 React 版本为 17.x(和类型包匹配):yarn add react@17.0.2 react-dom@17.0.2 yarn add @types/react-dom@17.0.20 --dev - Apollo 版本冲突:你同时安装了
@apollo/client@3.x和旧版的apollo-client@2.x、react-apollo@3.x,这些包会互相干扰。保留@apollo/client@3.x,删除所有旧版 Apollo 相关包:
3.x 的yarn remove apollo-client react-apollo @apollo/react-common @apollo/react-components @apollo/react-hoc @apollo/react-hooks@apollo/client已经包含了所有 hooks 和组件,不需要单独安装旧包。 - styled-components 版本问题:你用了 v6.0.0-rc.1 候选版本,Next.js 12 对它的兼容性可能有问题,降级到稳定的 v5.x:
yarn add styled-components@5.3.11 - ESLint 配置不匹配:
eslint-config-next是 11,和 Next.js 12 版本不一致,升级到 12.x:yarn add eslint-config-next@12 --dev
二、定位具体错误组件
- 开启 React 严格模式:在
_app.tsx中启用严格模式,会放大渲染错误,帮助定位问题:import { StrictMode } from 'react'; import type { AppProps } from 'next/app'; function MyApp({ Component, pageProps }: AppProps) { return ( <StrictMode> <Component {...pageProps} /> </StrictMode> ); } export default MyApp; - 逐步注释页面组件:先从首页开始,注释掉页面内的组件,逐个恢复,看哪个组件导致错误。如果是服务端渲染(SSR)的问题,可以先关闭页面的 SSR,用
dynamic导入组件禁用 SSR:import dynamic from 'next/dynamic'; const ProblemComponent = dynamic(() => import('../components/ProblemComponent'), { ssr: false, }); - 检查导入方式:这类错误大多是默认导入/命名导入搞混,比如:
- 错误:
import { Button } from './Button'但组件是默认导出export default Button - 错误:
import Button from './Button'但组件是命名导出export const Button = ...
可以用 VS Code 全局搜索查找可疑导入,或者开启 TypeScriptstrict模式,让编译错误提示导入不匹配的问题。
- 错误:
- 临时修改 React-Dom 源码打印信息:在报错的
renderElement函数里添加打印代码,输出当前要渲染的元素,找到那个类型为 object 的组件:
打开node_modules/react-dom/cjs/react-dom-server.browser.development.js,找到renderElement函数,在报错行前添加:
运行项目就能看到具体是哪个组件出问题。console.log('Rendering element:', element); console.log('Element type:', typeof element.type);
三、清理缓存和重新构建
- 执行清理命令:
yarn clean - 删除
yarn.lock,重新安装依赖:rm yarn.lock && yarn install - 重新构建项目:
yarn build
内容的提问来源于stack exchange,提问作者Atonic
相关产品推荐
相关产品推荐

