React:如何使用相同类型的多个上下文,同时允许 children 从所有上下文中读取数据

React: How to use multiple Contexts of the same type while allowing children to read data from all of them

我有一个类似于此的上下文设置

const DataContext = createContext({ data: null });

const getData = (key) => {
    switch(key) {
        case 1:
            return "Hello"
        case 2:
            return " World"
        default:
            return null
    }
}

export const DataProvider = ({ id, children }) => {

  const data = useMemo(() => {
    return getData(id);
  }, [id]);

  return (
    <DataContext.Provider
      value={{
        data,
      }}
    >
      {children}
    </DataContext.Provider>
  );
};

export default DataContext

和child个像这样使用它的组件

const HelloComponent = () => {
    return <DataProvider id={1}>
        {
            // children are components that useContext(DataContext) and expect data to be "Hello"
        }
    </DataProvider>
}

现在我需要这样做

const HelloWorldComponent = () => {
  return (
    <DataProvider id={1}>
      <DataProvider id={2}>
        {
          // children are components that need to read both Hello and World
        }
      </DataProvider>
    </DataProvider>
  );
};

需要将一个上下文定义的所有parent个上下文数据提供给一组children

我知道 useContext 只能读取给定 ContextType 中最接近的 parent,所以我不确定如何继续。

您不能使用相同类型的两个上下文提供程序并让子项从两者接收。上下文 API 使得子组件从 React 树中离它们最近的上下文提供者接收上下文值。

但是,您可以使用单个提供程序代替 returns getData 功能。这是一个使用单个 DataProvider 和自定义 React 挂钩来提供“id”值的示例。

Data.Context.js

import { createContext, useContext } from "react";

const DataContext = createContext({
  getData: () => {}
});

const getData = (key) => {
  switch (key) {
    case 1:
      return "Hello";
    case 2:
      return " World";
    default:
      return null;
  }
};

export const useDataContext = (id) => useContext(DataContext).getData(id);

const DataProvider = ({ children }) => {
  return (
    <DataContext.Provider value={{ getData }}>{children}</DataContext.Provider>
  );
};

export default DataProvider;

index.js

<DataProvider>
  <App />
</DataProvider>

子组件

import { useDataContext } from "./Data.Context";

const Child = () => {
  const data1 = useDataContext(1);
  const data2 = useDataContext(2);

  return (
    <div>
      <div>DataProvider 1: {data1}</div>
      <div>DataProvider 2: {data2}</div>
    </div>
  )
}