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

React中Context无法共享数据?自定义ServiceProvider调用异常排查

问题描述

手动创建Provider并访问Context的方式有效,但使用ServiceProvider实现共享服务(以便支持多服务扩展)时,组件无法访问内部Context,获取到的服务值为undefined。

代码示例

app.js

import React from 'react';
import TodosContainer from './TodosContainer';
import { TodoService } from './services/TodoService';
import { createServiceContext } from './ServiceProvider';

function App() {
  const { TodoServiceProvider } = createServiceContext('TodoService');
  return (
    <>
        <TodoServiceProvider service={TodoService}>
          <TodosContainer />
        </TodoServiceProvider>
    </>
  );
}

export default App;

serviceprovider.js

import React from 'react';

export function createServiceContext(name) {
    const ServiceContext = React.createContext();

    function ServiceProvider({ service, children }) {
        return (
            <ServiceContext.Provider value={service}>
                {children}
            </ServiceContext.Provider>
        );
    }

    return {
        [`${name}Context`]: ServiceContext,
        [`${name}Provider`]: ServiceProvider,
    };
}

TodosContainer.js

import { createServiceContext } from './ServiceProvider';
import { useContext } from 'react';

export default function TodosContainer() {
    const { TodoServiceContext } = createServiceContext('TodoService');
    const TodoSvc = useContext(TodoServiceContext);
    // 结果:TodoSvc 是 undefined
}
解决方案

核心问题

每次调用createServiceContext都会生成一个全新的React Context实例。App.js中创建的TodoServiceContext和TodosContainer.js中创建的TodoServiceContext是两个完全独立的对象,组件调用useContext时获取的是新Context的默认值(undefined),和Provider提供的Context毫无关联。

修复步骤

将Context的创建逻辑抽离到单独文件,确保全局只创建一次Context实例:

  1. 创建TodoServiceContext.js文件:
import { createServiceContext } from './ServiceProvider';

// 仅执行一次Context创建,导出对应的Context和Provider
export const { TodoServiceContext, TodoServiceProvider } = createServiceContext('TodoService');
  1. 修改App.js,直接导入已创建好的Provider:
import React from 'react';
import TodosContainer from './TodosContainer';
import { TodoService } from './services/TodoService';
import { TodoServiceProvider } from './TodoServiceContext';

function App() {
  return (
    <>
      <TodoServiceProvider service={TodoService}>
        <TodosContainer />
      </TodoServiceProvider>
    </>
  );
}

export default App;
  1. 修改TodosContainer.js,导入同一个Context实例:
import { useContext } from 'react';
import { TodoServiceContext } from './TodoServiceContext';

export default function TodosContainer() {
  const TodoSvc = useContext(TodoServiceContext);
  // 现在TodoSvc能正确获取到TodoService实例
}

原理说明

通过将Context的创建放在单独文件并导出,确保Provider组件和消费组件使用的是同一个Context实例,这样useContext才能正确关联到Provider提供的服务值,解决undefined的问题。

内容的提问来源于stack exchange,提问作者Nevyan Dimitrov Neykov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 23:05:18