Vite构建IIFE格式React组件库时useState钩子调用报错求助
问题分析与解决方案
核心问题原因
你直接调用组件函数(MyLib.DrawerShowdown())的方式违反了React钩子规则:钩子必须在React的组件渲染上下文内调用。这种直接执行函数的操作会让组件脱离React的渲染流程,导致React内部的组件上下文未初始化,进而出现Cannot read properties of null (reading 'useState')错误。未使用钩子的组件能运行仅因为它只是返回JSX元素,不依赖React的钩子上下文,但这并非正确的组件调用方式。
解决方案
1. 修正组件调用方式
必须通过React的渲染机制调用组件,而非直接执行函数,有两种实现方式:
方式A:使用JSX语法
需确保页面引入React和Babel(或使用已编译的JSX):
<div id="testreact"></div> <div id="testreact2"></div> <!-- 先引入React和ReactDOM的UMD包 --> <script src="https://unpkg.com/react@18/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script> <script src="./dist/my-lib.iife.js"></script> <!-- 使用type="text/babel"让浏览器编译JSX --> <script type="text/babel"> const { createRoot } = MyLib.ReactDOM; createRoot(document.getElementById('testreact')).render( <MyLib.ButtonShowdown /> ); createRoot(document.getElementById('testreact2')).render( <MyLib.DrawerShowdown /> ); </script>
方式B:使用React.createElement(无需Babel)
<div id="testreact"></div> <div id="testreact2"></div> <script src="https://unpkg.com/react@18/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script> <script src="./dist/my-lib.iife.js"></script> <script> const { createRoot } = MyLib.ReactDOM; const React = window.React; createRoot(document.getElementById('testreact')).render( React.createElement(MyLib.ButtonShowdown) ); createRoot(document.getElementById('testreact2')).render( React.createElement(MyLib.DrawerShowdown) ); </script>
2. 调整Vite配置,优化外部依赖处理
若希望组件库不打包React和ReactDOM(减小包体积),可修改Vite配置将其设为外部依赖,并指定全局变量映射:
import { defineConfig } from 'vite' import { resolve } from 'path'; import react from '@vitejs/plugin-react-swc' export default defineConfig({ define: { 'process.env': process.env }, plugins: [react()], build: { lib: { entry: resolve(__dirname, 'lib/main.js'), name: 'MyLib', fileName: 'my-lib', formats: ['iife'] }, rollupOptions: { // 声明外部依赖,不打包进组件库 external: ['react', 'react-dom'], output: { // 映射外部依赖到全局变量 globals: { react: 'React', 'react-dom': 'ReactDOM' } } } }, })
配置后需在页面中先引入React和ReactDOM的UMD包,再引入你的组件库。
内容的提问来源于stack exchange,提问作者DEV SL
相关产品推荐
相关产品推荐

