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

React传递对象Props到Context组件时属性值undefined问题求助

React Context 数据传递问题修复方案

问题概述

将sujets对象通过SujetsProvider传递给Header组件时出现异常:

  • SujetsProvider中能打印完整sujets对象,但无法读取其内部属性(如sujets.B1_logique),属性值均为undefined
  • Header组件可正常获取Context中的exemple值(Hello World),但sujets始终为undefined
  • 控制台抛出错误:Uncaught TypeError: Cannot read properties of undefined (reading 'B1_Logique')

核心原因

  1. 双Provider冲突:Header位于AppLayout组件内的SujetsProvider子树中,但该Provider未传入sujets props;而GrilleSujets组件内的SujetsProvider虽传入了sujets,但Header不在其组件树范围内,导致Header获取的是无sujets值的Context。
  2. 状态作用域错误:sujets状态仅存在于GrilleSujets组件内部,无法被上层的AppLayout中的Provider共享。

修复步骤

1. 状态提升

将useReducer的状态逻辑提升到AppLayout组件(或更上层共享组件),确保所有需要访问sujets的组件都处于同一个Context Provider的覆盖范围内。

2. 统一Context Provider

移除GrilleSujets内的独立SujetsProvider,通过AppLayout中的单一Provider传递sujets和状态更新方法。

3. 安全访问属性

使用可选链操作符?.避免因sujets为undefined导致的报错。

代码修改示例

修改AppLayout组件

import { useReducer } from "react";
import { SujetsProvider } from "./SujetsProvider";
import StyledAppLayout from "./StyledAppLayout";
import Header from "./Header";
import Sidebar from "./Sidebar";
import Main from "./Main";
import { Outlet } from "react-router-dom";

// 定义初始状态和reducer
const initialState = {
  B1_logique: 0,
  B2_accueil: 0,
  B3_prise_en_charge: 0,
  // 其他属性...
};

function reducer(sujets, action) {
  // 你的reducer逻辑
  switch (action.type) {
    case "B1_LOGIQUE":
      return {...sujets, B1_logique: sujets.B1_logique + 1};
    // 其他case...
    default:
      return sujets;
  }
}

export default function AppLayout() {
  const [sujets, dispatch] = useReducer(reducer, initialState);

  return (
    <SujetsProvider sujets={sujets} dispatch={dispatch}>
      <StyledAppLayout>
        <Header />
        <Sidebar />
        <Main>
          {/* 通过Outlet传递dispatch给子组件(如GrilleSujets) */}
          <Outlet context={{ dispatch }} />
        </Main>
      </StyledAppLayout>
    </SujetsProvider>
  );
}

修改GrilleSujets组件

import StyledGrille from "./StyledGrille";

export default function GrilleSujets({ dispatch }) {
  const handleClick = (val) => {
    dispatch({ type: val });
  };

  return (
    <StyledGrille>
      {/* 你的组件内容,比如按钮触发handleClick */}
      <button onClick={() => handleClick("B1_LOGIQUE")}>增加B1分值</button>
      ...
    </StyledGrille>
  );
}

修改SujetsProvider组件

import { createContext, useContext } from "react";

// 初始化Context时设置默认值,避免undefined报错
const SujetsContext = createContext({
  sujets: {},
  exemple: "",
  dispatch: () => {}
});

function SujetsProvider({ sujets, dispatch, children }) {
  const val = "Hello World";

  return (
    <SujetsContext.Provider value={{ sujets, exemple: val, dispatch }}>
      {children}
    </SujetsContext.Provider>
  );
}

function useSujets() {
  return useContext(SujetsContext);
}

export { SujetsProvider, useSujets };

修改Header组件

import { useSujets } from "./SujetsProvider";
import StyledHeader from "./StyledHeader";

function Header() {
  const { sujets, exemple } = useSujets();

  return (
    <StyledHeader>
      Header - B1逻辑分值:{sujets?.B1_logique} {exemple}
    </StyledHeader>
  );
}

export default Header;

额外检查

  • 确保initialState的结构与预期的sujets对象完全一致,所有需要访问的属性都有初始值
  • 确认所有消费Context的组件都在SujetsProvider的子树范围内

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 19:40:37