You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 19:33:20