Vite构建React库在Next.js中报错:Cannot read properties of null (reading 'useRef')
问题:React组件库在Next.js中运行报错
TypeError: Cannot read properties of null (reading 'useRef') 我用Vite构建了一个React组件库,配置及代码如下:
组件库代码与配置
src/components/index.js
import { useRef } from 'react' export function Foo() { const ref = useRef() return <div ref={ref}>Hi!</div> }
vite.config.js
import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import { resolve } from 'node:path' export default defineConfig({ plugins: [react()], build: { lib: { entry: resolve('src', 'components/index.js'), // other stuff }, manifest: true, rollupOptions: { external: ['react', 'react-dom'], output: { globals: { react: 'React', 'react-dom': 'ReactDOM', }, }, }, } })
package.json
{ "name": "foo", "type": "module", "exports": { ".": { "import": "./dist/foo.es.js", "require": "./dist/foo.umd.js" } }, "scripts": { "dev": "vite", "build": "rm -rf dist && vite build", "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview" }, "devDependencies": { // some dev depencencies }, "peerDependencies": { "react": "^18.2.0", "react-dom": "^18.2.0" } }
Next.js测试项目配置
package.json
{ "name": "example-nextjs-app", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "foo": "link:../../foo", "next": "14.0.4", "react": "^18", "react-dom": "^18" }, "devDependencies": { // some dev depencencies } }
组件使用代码
import { Foo } from 'foo' export function Header() { return <Foo /> }
操作流程:组件库目录执行pnpm install+pnpm run build,Next.js项目目录执行pnpm install+pnpm run dev,访问页面时触发运行时错误:TypeError: Cannot read properties of null (reading 'useRef')。
解决方案
这个错误的核心是React双实例冲突:组件库通过link方式引入时,加载了自身node_modules里的React,和Next.js项目的React实例重复,导致Hooks无法正常绑定到正确的React上下文。
方案1:修改组件库的peerDependencies配置
在组件库的package.json中添加peerDependenciesMeta,标记React和ReactDOM为可选,避免link时本地安装重复依赖:
{ // ... 其他原有配置 "peerDependencies": { "react": "^18.2.0", "react-dom": "^18.2.0" }, "peerDependenciesMeta": { "react": { "optional": true }, "react-dom": { "optional": true } } }
方案2:Next.js中强制使用项目自身的React
在Next.js项目根目录新建/修改next.config.js,添加webpack别名配置,强制组件库使用项目的React实例:
const path = require('path') /** @type {import('next').NextConfig} */ const nextConfig = { webpack: (config) => { config.resolve.alias = { ...config.resolve.alias, react: path.resolve('./node_modules/react'), 'react-dom': path.resolve('./node_modules/react-dom'), } return config }, } module.exports = nextConfig
方案3:用pnpm配置提升React依赖
在组件库目录新建.npmrc文件,添加以下配置,强制React相关依赖被提升到顶层node_modules,避免双实例:
public-hoist-pattern[]=react public-hoist-pattern[]=react-dom
方案4:改用本地包安装替代link
如果link模式的问题难以排查,可以直接打包组件库为本地包安装:
- 组件库目录执行:
pnpm pack,生成foo-x.x.x.tgz文件 - 修改Next.js项目的
package.json依赖:"dependencies": { "foo": "../foo/foo-x.x.x.tgz", // ... 其他依赖 } - 执行
pnpm install重新安装依赖
内容的提问来源于stack exchange,提问作者allevo
相关产品推荐
相关产品推荐

