Как создать метод в контексте, который может быть доступен дочерним компонентам?

#reactjs #react-native #react-context

#reactjs #react-native #реагировать-контекст

Вопрос:

У меня есть компонент, который отображает:

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

Я не понимаю, как создать метод, доступный следующим образом:

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

Комментарии:

1. Эй .. Вы хотите передать метод компоненту Button

2. У вас есть codesandbox , на который мы могли бы взглянуть?

Ответ №1:

Потребительский компонент

Вам нужно использовать контекст через Context.Consumer , который является прямым потомком соответствующего Provider . В документах есть достойные примеры, хотя в них сочетаются классовые и функциональные компоненты. Обновление контекста из вложенного компонента

Песочница: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

useContext Крючок также доступен и, возможно, обеспечивает более знакомый рисунок. Потребитель контекста по-прежнему должен быть потомком Поставщика, но доступ к нему осуществляется через перехват, а не через потребительский компонент.

Песочница: 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>;
}
  

Ответ №2:

В документах Context advisorumer на самом деле рассказывается все, что вам нужно знать:

Компонент React, который подписывается на изменения контекста. Это позволяет вам подписаться на контекст внутри функционального компонента.

Требуется функция в качестве дочерней. Функция получает текущее значение контекста и возвращает узел React. Аргумент value, передаваемый функции, будет равен значению prop ближайшего поставщика для этого контекста выше в дереве. Если для этого контекста выше нет поставщика, аргумент value будет равен defaultValue, который был передан в 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>
  

Также важно, чтобы потребительский компонент находился внутри поставщика.