我目前正在使用 TypeScript 和 Rollup 从 Material UI 创建组件库。我已经成功发布了该包,但是当我尝试将其导入新项目时,出现以下错误:
“未捕获类型错误:无法读取 null 的属性(读取‘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 和 React DOM 而导致问题的问题,请删除这些包并将以下代码段添加到 package.json 文件中应该可以解决该问题:
"peerDependencies": {
"@emotion/react": "^11.5.0",
"@emotion/styled": "^11.3.0",
"@types/react": "^17.0.0 || ^18.0.0",
"react": "^17.0.0 || ^18.0.0",
"react-dom": "^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@emotion/react": {
"optional": true
},
"@emotion/styled": {
"optional": true
}
}
通过将这些对等依赖项添加到 package.json 文件中,您可以指定代码正常运行所需的包版本。 “可选”:true标志允许这些包作为可选依赖项安装,这意味着它们不会被多次安装并导致冲突。
确保在更新 package.json 文件后运行 npm install 或 yarn install 以确保更改生效。这应该可以解决多次安装 React 和 React DOM 的任何问题,并确保您的代码顺利运行。
我的组件库和 MUI 的 Datepicker-Pro 也遇到了类似的问题。在我的组件库中,我使用 useContext 来访问 MUI 的日期实用程序。
当我在本地运行项目或在 XAMP/MAMP 服务器上进行生产构建时,没有任何问题,因此我的组件库可以无缝集成到项目中。但是,通过 GitLab 中的 CI 部署到服务器会导致错误,并在
const {utils} = useContext(MuiPickersAdapterContext)
中显示消息“null 不是对象”。
我尝试通过尝试不同的软件包版本来解决该问题,但找不到解决方案。我注意到我在本地使用 Yarn Berry (4.0.2),在 CI 中使用 YARN Classic。值得注意的是,我没有切换到 pnp 模式并继续在节点模块模式下工作。
为了彻底解决问题,我使用 Yarn Classic 创建了项目并将其部署到 MAMP,却遇到了同样的错误。为了确认包管理器的效果,我删除了yarn.lock和node_modules,恢复到Yarn Berry(4.0.2),运行yarn install并重建了项目。正如预期的那样,该错误已修复。
PS:我已经确保了我的项目和组件库中 Mui 和 Emotion 包的版本控制的一致性。