Vue宿主+React远程组件的微前端useState报错问题求助
问题
搭建Vue宿主+React远程组件的微前端应用(基于Vite和vite-plugin-federation),未使用useState时功能正常,一旦引入useState就抛出错误:Uncaught (in promise) TypeError: Cannot read properties of null (reading 'useState')
宿主应用代码
App.vue
<script setup lang="ts"> import { onMounted, ref } from 'vue' import ReactDOMServer from 'react-dom/server' const componentHtml = ref() onMounted( async () => (componentHtml.value = ReactDOMServer.renderToString((await import('home/Home')).default())) ) </script> <template> <div v-html="componentHtml"></div> </template>
vite.config.ts
import { fileURLToPath, URL } from 'node:url' import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import federation from '@originjs/vite-plugin-federation' export default defineConfig({ plugins: [ vue(), federation({ name: 'layout', filename: 'remoteEntry.js', remotes: { home: 'http://localhost:4173/assets/remoteEntry.js' } }) ], resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } } })
远程应用代码
App.jsx
import { useState } from "react"; export default function App() { const [value] = useState("react"); return <div>{value}</div>; }
vite.config.js
import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; import federation from "@originjs/vite-plugin-federation"; export default defineConfig({ plugins: [ react(), federation({ name: "home", filename: "remoteEntry.js", exposes: { "./Home": "./src/App.jsx", }, }), ], });
解决方案
问题核心是React依赖未正确共享,且服务端渲染方式不支持React Hooks,按以下步骤修复:
1. 配置共享React依赖
在宿主和远程应用的vite配置中,添加shared字段,将react和react-dom设为单例共享,确保两端使用同一个React实例:
远程应用 vite.config.js 修改后
import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; import federation from "@originjs/vite-plugin-federation"; export default defineConfig({ plugins: [ react(), federation({ name: "home", filename: "remoteEntry.js", exposes: { "./Home": "./src/App.jsx", }, shared: { react: { singleton: true, requiredVersion: "^18.0.0" }, "react-dom": { singleton: true, requiredVersion: "^18.0.0" } } }), ], });
宿主应用 vite.config.ts 修改后
import { fileURLToPath, URL } from 'node:url' import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import federation from '@originjs/vite-plugin-federation' export default defineConfig({ plugins: [ vue(), federation({ name: 'layout', filename: 'remoteEntry.js', remotes: { home: 'http://localhost:4173/assets/remoteEntry.js' }, shared: { react: { singleton: true, requiredVersion: "^18.0.0" }, "react-dom": { singleton: true, requiredVersion: "^18.0.0" } } }) ], resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } } })
2. 改用客户端方式挂载React组件
React Hooks只能在客户端渲染流程中正常工作,替换原有的服务端渲染逻辑,改为动态挂载到DOM节点:
宿主应用 App.vue 修改后
<script setup lang="ts"> import { onMounted, ref } from 'vue' import React from 'react' import ReactDOM from 'react-dom/client' const container = ref(null) onMounted(async () => { const Home = (await import('home/Home')).default if (container.value) { const root = ReactDOM.createRoot(container.value) root.render(<Home />) } }) </script> <template> <div ref="container"></div> </template>
3. 重启项目
修改配置后,重启宿主和远程应用的开发服务,即可正常使用useState等React Hooks。
内容的提问来源于stack exchange,提问作者vova
相关产品推荐
相关产品推荐

