如何在子组件可以访问的上下文中创建方法?

How can create a method in context that can be accessible by child components?

我有一个呈现的组件:

<View>
   <SomeContext.Provider value={state}>
        {props.children}
   </SomeContext.Provider>
</View>

我不明白如何创建可通过以下方式访问的方法:

<View>
   <SomeContext.Provider>
        {(method) =>  
                <Button
                   title={"Magic"}
                   onPress={() => {
                     method()
                   }}
                 ></Button>
        }
   </SomeContext.Provider>
</View>

Context counsumer docs实际上告诉你你需要知道的一切:

A React component that subscribes to context changes. This lets you subscribe to a context within a function component.

Requires a function as a child. The function receives the current context value and returns a React node. The value argument passed to the function will be equal to the value prop of the closest Provider for this context above in the tree. If there is no Provider for this context above, the value argument will be equal to the defaultValue that was passed to createContext().

因此,在您的示例中,您需要将所需的方法传递给提供者:

const method = () => {};

<View>
  <SomeContext.Provider value={{ method }}>
    {props.children}
  </SomeContext.Provider>
</View>

然后在 Consumer 中你可以这样调用它:

<View>
  <SomeContext.Consumer>
    // using destructuring here,
    // so its ({ method }) instead of (method)
    {({ method }) =>  
      <Button
        title={"Magic"}
        onPress={() => method()} />
    }
  </SomeContext.Consumer>
</View>

此外,消费者组件在提供者内部也很重要。

消费者组件

您需要通过 Context.Consumer 使用上下文,该 Context.Consumer 是相关 Provider 的直接后代。文档有不错的示例,尽管它们混合了 class-based 和功能组件。 Updating Context from a Nested Component

沙盒:https://codesandbox.io/s/react-context-consumer-passing-method-to-nested-child-forked-u0bi8

const initData = {
  data: { a: "Text from Context", b: "2" },
  method: () => {
    console.log("Method called.");
  }
};

const SomeContext = React.createContext();

export default function App() {
  return (
    <SomeContext.Provider value={initData}>
      <Content />
    </SomeContext.Provider>
  );
}

function Content() {
  return (
    <div>
      <SomeButton />
    </div>
  );
}

function SomeButton() {
  return (
    <SomeContext.Consumer>
      {({ data, method }) => <button onClick={method}>{data.a}</button>}
    </SomeContext.Consumer>
  );
}


useContext Hook

useContext 挂钩也可用,并且可能提供更熟悉的模式。 context 的 Consumer 仍然需要是 Provider 的后代,但它是通过钩子访问的,而不是通过 Consumer 组件。

沙盒:https://codesandbox.io/s/react-context-passing-method-to-nested-child-1fcno

const initData = {
  data: { a: "Text from Context", b: "2" },
  method: () => {
    console.log("Method called.");
  }
};

const SomeContext = React.createContext();

export default function App() {
  return (
    <SomeContext.Provider value={initData}>
      <Toolbar />
    </SomeContext.Provider>
  );
}

function Toolbar(props) {
  return (
    <div>
      <SomeButton />
    </div>
  );
}

function SomeButton() {
  const { data, method } = React.useContext(SomeContext);
  return <button onClick={method}>{data.a}</button>;
}