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

如何让不同createRoot渲染的函数组件共享React Context(无需Redux)

问题:如何在两个通过不同createRoot渲染的函数组件间共享上下文?

当前问题:<Annotation>组件获取的状态与<Chat>组件不一致。

限制条件:无法使用Redux,应用体量很小因此未采用。

需要修改context.js实现状态共享,现有代码如下:

index.js

import { AppContext, AppContextProvider } from "./context";
const BookBot = (props) => {
    const botRoot = createRoot(document.getElementById((props?.toolbox)))
    const botAnnot = createRoot(document.getElementById((props?.annotbox)))
    botRoot.render(
        <AppContextProvider>
            <Chat />
        </AppContextProvider>
    );
    botAnnot.render(
        <AppContextProvider>
            <Annotation />
        </AppContextProvider>
    )
}

context.js

const AppContext = React.createContext([{}, () => {}]);

const AppContextProvider = (props) => {
  const [state, setState] = useState({
    chats:[],
    query:undefined,
    sendDisabled:false,
    chatId:""
  });
  return (
    <AppContext.Provider value={[state, setState]}>
      {props.children}
    </AppContext.Provider>
    );
};

export { AppContext, AppContextProvider };

解决方案

问题核心在于你给两个独立的createRoot分别套了一个AppContextProvider,每个Provider内部都创建了独立的useState状态实例,导致两个组件的状态完全隔离。要实现共享,需让两个Provider复用同一个状态,以下是两种可行方案:

方案1:让Provider接收外部传入的状态(推荐)

把AppContextProvider改为受控组件,不再内部创建状态,而是通过props接收外部的状态和更新方法:

修改context.js

const AppContext = React.createContext([{}, () => {}]);

// 改为接收外部传入的state和setState
const AppContextProvider = (props) => {
  const { state, setState, children } = props;
  return (
    <AppContext.Provider value={[state, setState]}>
      {children}
    </AppContext.Provider>
  );
};

export { AppContext, AppContextProvider };

修改index.js

将状态提升到BookBot组件中,把同一个state和setState传递给两个Provider:

import { useState } from 'react';
import { AppContext, AppContextProvider } from "./context";
const BookBot = (props) => {
    // 在这里创建共享状态
    const [state, setState] = useState({
        chats:[],
        query:undefined,
        sendDisabled:false,
        chatId:""
    });
    
    const botRoot = createRoot(document.getElementById((props?.toolbox)))
    const botAnnot = createRoot(document.getElementById((props?.annotbox)))
    
    botRoot.render(
        <AppContextProvider state={state} setState={setState}>
            <Chat />
        </AppContextProvider>
    );
    botAnnot.render(
        <AppContextProvider state={state} setState={setState}>
            <Annotation />
        </AppContextProvider>
    )
}

这样修改后,两个组件将共享同一个状态实例,状态变更时会同步更新。

方案2:使用全局状态单例(小型应用可选)

如果不想修改Provider结构,可在context.js中创建全局状态单例(不推荐大型应用使用):

修改context.js

const AppContext = React.createContext([{}, () => {}]);

// 创建全局状态单例
let globalState;
let globalSetState;

const AppContextProvider = (props) => {
  const [state, setState] = useState({
    chats:[],
    query:undefined,
    sendDisabled:false,
    chatId:""
  });
  
  // 仅在首次渲染时初始化全局状态
  if (!globalState) {
    globalState = state;
    globalSetState = setState;
  }
  
  // 所有Provider复用全局状态
  return (
    <AppContext.Provider value={[globalState, globalSetState]}>
      {props.children}
    </AppContext.Provider>
  );
};

export { AppContext, AppContextProvider };

这种方式无需修改index.js,但要注意:只有第一个渲染的AppContextProvider会初始化全局状态,后续Provider都会复用该状态。


内容的提问来源于stack exchange,提问作者MN_

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 19:34:52