基于Material UI的组件库导入时出现useContext空值读取错误求助
问题
我正在使用TypeScript和Rollup开发基于Material UI的组件库,已成功发布该包,但将其导入新项目时,出现错误:Uncaught TypeError: Cannot read properties of null (reading 'useContext')。本地测试时库运行正常,我已检查依赖项,似乎一切正常。求解决建议。
package.json
{ "name": "*****", "version": "0.1.24", "engines": { "node": ">=8.3.0" }, "publishConfig": { "registry": "https://npm.pkg.github.com" }, "repository": "https://github.com/****/****.git", "babel": { "presets": [ [ "react-app", { "absoluteRuntime": false } ] ] }, "dependencies": { "@changesets/cli": "^2.26.0", "@emotion/react": "^11.10.6", "@emotion/styled": "^11.10.6", "@fontsource/dm-sans": "^4.5.9", "@fontsource/material-icons": "^4.5.4", "@mui/icons-material": "^5.11.11", "@mui/material": "^5.11.10", "@tabler/icons": "2.6.0", "@tabler/icons-react": "2.7.0", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "@types/jest": "^27.5.2", "@types/node": "^16.18.12", "@types/react": "^18.0.28", "@types/react-dom": "^18.0.11", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1", "web-vitals": "^2.1.4" }, "scripts": { "start": "react-scripts start", "build": "cross-env BABEL_ENV=production babel src -d dist", "test": "react-scripts test", "eject": "react-scripts eject", "storybook": "start-storybook -p 6006 -s public", "build-storybook": "build-storybook -s public", "prepare": "husky install", "release": "npm publish && yarn changeset", "rollup": "rollup -c" }, "eslintConfig": { "extends": [ "react-app", "react-app/jest" ], "overrides": [ { "files": [ "**/*.stories.*" ], "rules": { "import/no-anonymous-default-export": "off" } } ] }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] }, "devDependencies": { "@babel/cli": "^7.21.0", "@rollup/plugin-commonjs": "^24.0.1", "@rollup/plugin-image": "^3.0.2", "@rollup/plugin-node-resolve": "^15.0.1", "@rollup/plugin-terser": "^0.4.0", "@rollup/plugin-typescript": "^11.0.0", "@rollup/plugin-url": "^8.0.1", "@storybook/addon-actions": "^6.5.16", "@storybook/addon-essentials": "^6.5.16", "@storybook/addon-interactions": "^6.5.16", "@storybook/addon-links": "^6.5.16", "@storybook/builder-webpack5": "^6.5.16", "@storybook/manager-webpack5": "^6.5.16", "@storybook/node-logger": "^6.5.16", "@storybook/preset-create-react-app": "^4.1.2", "@storybook/react": "^6.5.16", "@storybook/testing-library": "^0.0.13", "@typescript-eslint/eslint-plugin": "^5.54.0", "@typescript-eslint/parser": "^5.54.0", "auto": "^10.43.0", "babel-plugin-named-exports-order": "^0.0.2", "cross-env": "^7.0.3", "eslint": "^8.35.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb-typescript": "^17.0.0", "eslint-config-node": "^4.1.0", "eslint-config-prettier": "^8.6.0", "eslint-plugin-import": "^2.27.5", "eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-simple-import-sort": "^10.0.0", "file-loader": "^6.2.0", "husky": "^8.0.0", "prettier": "^2.8.4", "prop-types": "^15.8.1", "rollup": "^3.20.2", "rollup-plugin-dts": "^5.3.0", "rollup-plugin-peer-deps-external": "^2.2.4", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-terser": "^7.0.2", "style-loader": "^3.3.1", "typescript": "^4.9.5", "webpack": "^5.75.0" }, "lint-staged": { "*": [ "eslint src --ext .js,.jsx,.ts,.tsx --fix", "prettier --write src" ] }, "main": "dist/cjs/index.js", "module": "dist/esm/index.js", "files": [ "dist" ], "types": "dist/index.d.ts", "type": "module" }
rollup.config.js
import commonjs from '@rollup/plugin-commonjs'; import resolve from '@rollup/plugin-node-resolve'; import typescript from '@rollup/plugin-typescript'; import url from '@rollup/plugin-url'; import dts from 'rollup-plugin-dts'; import external from 'rollup-plugin-peer-deps-external'; import postcss from 'rollup-plugin-postcss'; import { terser } from 'rollup-plugin-terser'; import packageJson from './package.json' assert { type: 'json' }; export default [ { input: 'src/index.tsx', output: [ { file: packageJson.main, format: 'cjs', sourcemap: true, name: 'react-ts-lib', }, { file: packageJson.module, format: 'esm', sourcemap: true, }, ], plugins: [ url({ // by default, rollup-plugin-url will not handle font files include: ['**/*.woff', '**/*.woff2'], // setting infinite limit will ensure that the files // are always bundled with the code, not copied to /dist limit: Infinity, }), external(), resolve(), commonjs(), typescript({ tsconfig: './tsconfig.json' }), postcss(), terser(), ], }, { input: 'dist/esm/types/index.d.ts', output: [{ file: 'dist/index.d.ts', format: 'esm' }], external: [/\.css$/], plugins: [dts()], }, ];
解决方案建议
迁移React及MUI依赖到peerDependencies
当前package.json把react、react-dom、@mui/material等核心依赖放在了dependencies中,这会导致组件库和导入它的新项目各自打包一份React实例,出现上下文不匹配的问题,直接引发useContext报错。调整方式:"peerDependencies": { "react": "^18.0.0", "react-dom": "^18.0.0", "@mui/material": "^5.11.0", "@emotion/react": "^11.0.0", "@emotion/styled": "^11.0.0" }, "devDependencies": { // 保留这些依赖的开发版本,比如react@18.2.0、@mui/material@5.11.10等 }同时删除
dependencies中对应的条目。确认Rollup的外部依赖配置
虽然用了rollup-plugin-peer-deps-external,但可以手动在Rollup配置中明确添加外部依赖,避免意外打包:// 在第一个Rollup配置对象中添加 external: ['react', 'react-dom', '@mui/material', '@emotion/react', '@emotion/styled', '@mui/icons-material'],统一React版本
确保导入组件库的新项目使用的React主版本和组件库peerDependencies中声明的一致,避免版本差异导致的兼容性问题。清理缓存重新构建发布
删除本地dist目录,执行rollup -c重新构建,再重新发布包,避免缓存带来的旧代码问题。
内容的提问来源于stack exchange,提问作者Mayur Sonawane
相关产品推荐
相关产品推荐

