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

使用Context API实现父子及同级组件传值并解决渲染错误

解决Context API的TypeError及多组件数据消费问题

先来说你遇到的错误:

你看到的TypeError: render is not a function和Context Consumer需传入单个函数作为子元素警告,本质是同一个问题——你给AppContext.Consumer的子元素不是直接的渲染函数,而是套了一层<div>。Consumer的规则很明确:它必须直接接收一个函数作为子节点,这个函数会拿到Provider传递的上下文数据,然后返回要渲染的JSX。你现在把函数放在<div>里,Consumer识别不了这个函数,自然就报错了。

另外还有个隐藏问题:你的<AppContext.Provider>没有传递value属性,就算Consumer用对了,也拿不到App组件里的appData数据。


先修正当前的AppDataList组件和App组件

修正后的App.js

import React, { Component } from "react";
import "./App.css";
import AppDataList from "./components/AppDataList";
export const AppContext = React.createContext();

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = { appData: [] };
  }

  fetchAppData() {
    fetch(`http://localhost:4000/AppDataList`)
      .then(res => res.json())
      .then(res => {
        console.log(res)
        this.setState({ appData: res });
      });
  }

  componentDidMount() {
    this.fetchAppData();
  }

  render() {
    return (
      <div className="App">
        {/* 必须通过value把要共享的数据传给Provider */}
        <AppContext.Provider value={this.state.appData}>
          <AppDataList />
        </AppContext.Provider>
      </div>
    );
  }
}

修正后的AppDataList.js

import React, { Component } from "react";
import { AppContext } from "../App";

export default class AppDataList extends Component {
  render() {
    return (
      <AppContext.Consumer>
        {/* 直接传递函数,参数就是Provider传来的appData */}
        {appData => (
          <div>
            {/* 这里根据你的实际数据结构渲染,比如数组用map遍历 */}
            {appData.length > 0 ? (
              appData.map((item, index) => (
                <p key={index}>{JSON.stringify(item)}</p>
              ))
            ) : (
              <p>数据加载中...</p>
            )}
          </div>
        )}
      </AppContext.Consumer>
    );
  }
}

实现多组件(Child1/Child2/Child3)消费数据的方案

只需要把这三个组件都放在AppContext.Provider的包裹范围内,然后每个组件按照正确的方式消费Context即可。

调整App.js包裹多组件

import React, { Component } from "react";
import "./App.css";
import Child1 from "./components/Child1";
import Child2 from "./components/Child2";
import Child3 from "./components/Child3";
export const AppContext = React.createContext();

export default class App extends Component {
  // 之前的state、fetchAppData、componentDidMount逻辑保持不变

  render() {
    return (
      <div className="App">
        <AppContext.Provider value={this.state.appData}>
          {/* 把所有需要消费数据的子组件放在Provider内部 */}
          <Child1 />
          <Child2 />
          <Child3 />
        </AppContext.Provider>
      </div>
    );
  }
}

子组件消费数据的两种方式

方式1:类组件用Consumer(和AppDataList一致)

以Child1为例:

// Child1.js
import React, { Component } from "react";
import { AppContext } from "../App";

export default class Child1 extends Component {
  render() {
    return (
      <AppContext.Consumer>
        {appData => (
          <div className="child1">
            <h3>Child1 展示数据</h3>
            {appData.length > 0 ? (
              appData.map((item, idx) => (
                <div key={idx}>{item.name}</div> {/* 替换成你数据里的实际字段 */}
              ))
            ) : (
              <p>暂无数据</p>
            )}
          </div>
        )}
      </AppContext.Consumer>
    );
  }
}
方式2:函数组件用useContext钩子(更简洁)

如果你的子组件是函数组件,推荐用React的useContext钩子,代码更清爽,以Child2为例:

// Child2.js
import React, { useContext } from "react";
import { AppContext } from "../App";

export default function Child2() {
  // 直接拿到上下文数据
  const appData = useContext(AppContext);

  return (
    <div className="child2">
      <h3>Child2 展示数据</h3>
      {appData.length === 0 ? (
        <p>加载中...</p>
      ) : (
        <ul>
          {appData.map((item, idx) => (
            <li key={idx}>{item.description}</li> {/* 替换成实际字段 */}
          ))}
        </ul>
      )}
    </div>
  );
}

关键要点总结

  • <AppContext.Provider>必须通过value属性传递需要共享的数据
  • <AppContext.Consumer>的子元素必须是单个函数,不能嵌套其他元素,这个函数接收Provider的value作为参数,返回渲染的JSX
  • 函数组件优先使用useContext钩子,代码更简洁易读

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 15:13:14