我正在尝试将我的代码分成单独的包以模块化我的反应应用程序;这样做需要我在一个单独的库中创建反应组件,该库使用
useState
管理状态。
但是,当在反应应用程序中利用库的组件时,我收到此错误:
null is not an object (evaluating 'dispatcher.useState')
useState@http://localhost:3000/static/js/bundle.js:7493:24
Counter@http://localhost:3000/static/js/bundle.js:6017:65
renderWithHooks@http://localhost:3000/static/js/bundle.js:22612:31
mountIndeterminateComponent@http://localhost:3000/static/js/bundle.js:25896:32
这是我的设置:
反应库 — package.json
{
"name": "lib-five",
"version": "1.0.0",
"description": "",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
"types": "./dist/esm/index.d.ts",
"scripts": {
"prepare": "npm run build",
"build": "yarn build:esm && yarn build:cjs",
"build:esm": "tsc",
"build:cjs": "tsc --module commonjs --outDir dist/cjs"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@types/react": "^18.2.48",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"typescript": "^5.3.3"
},
"peerDependencies": {
"react": ">=16"
},
"files": [
"dist"
]
}
计数器.tsx
import React, { useState } from 'react'
export const Counter: React.FC<{}> = () => {
const [count, setCount] = useState<number>(0)
const increment = () => setCount((c) => c + 1)
const decrement = () => setCount((c) => c - 1)
return (
<div>
<h1>Counter</h1>
<p>Count: { count }</p>
<button onClick={ increment}>Increment</button>
<button onClick={ decrement }>Decrement</button>
</div>
)
}
index.ts
import { Counter } from './Counter'
export { Counter }
React 应用程序(使用库) — package.json
{
"name": "uselibtest",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^27.5.2",
"@types/node": "^16.18.68",
"@types/react": "^18.2.47",
"@types/react-dom": "^18.2.18",
"lib-five": "file:../lib-five",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"typescript": "^4.9.5",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
App.tsx
import React
import { Counter } from 'lib-five'
function App() {
return (
<div style={ containerStyle }>
<Counter />
</div>
)
}
export default App
此外,如果您的库和主应用程序使用“相同版本”的 React,并且我们在库中外部化 React 构建配置,我们可以避免调度程序为空错误。这可以确保像 useState 这样的钩子在模块化 React 应用程序中正常工作。 我们还需要确保在 lib- Five 和 main-app 中使用相同版本的 @types/react 和 @types/react-dom 。 \
更新 lib- Five>vite.config.json 将react和react-dom标记为外部依赖项。
\
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import dts from 'vite-plugin-dts';
export default defineConfig({
plugins: [react(), dts()],
build: {
lib: {
entry: 'src/index.ts',
name: 'LibFive',
fileName: (format) => `lib-five.${format}.js`,
},
rollupOptions: {
external: ['react', 'react-dom'],
output: {
globals: {
react: 'React',
'react-dom': 'ReactDOM',
},
},
},
},
});
yarn build
重建主应用程序
npm install --save ../lib-five
npm dedupe