В документации React говорится, что функцию, определенную в корневом компоненте, следует передавать в качестве реквизита дочернему компоненту, если вы планируете обновлять контекст из вложенного компонента.
Я реализовал то же самое:
import React from 'react';
const DataContext = React.createContext();
/**
* The App.
*/
export default class App extends React.Component {
constructor() {
super();
this.updateGreet = this.updateGreet.bind( this );
this.state = {
greet: '',
updateGreet: this.updateGreet
}
}
updateGreet() {
this.setState({
greet: 'Hello, User',
});
}
render() {
return (
<DataContext.Provider value = { this.state }>
<GreetButton />
<DisplayBox />
</DataContext.Provider>
)
}
}
/**
* Just a button element. On clicking it sets the state of `greet` variable.
*/
const GreetButton = () => {
return (
<DataContext.Consumer>
{
( { updateGreet } ) => {
return <button onClick = { updateGreet }>Greet</button>
}
}
</DataContext.Consumer>
)
}
/**
* Prints the value of `greet` variable between <h1> tags.
*/
const DisplayBox = () => {
return (
<DataContext.Consumer>
{
( { greet } ) => {
return <h1>{ greet }</h1>
}
}
</DataContext.Consumer>
)
}
Это очень простое приложение React, которое я создал для изучения Context API. Чего я пытаюсь добиться, так это определить метод updateGreet() в компоненте GreetButton вместо того, чтобы определять его внутри компонента App, поскольку функция не имеет ничего общего с компонентом App.
Еще одно преимущество, которое я вижу, заключается в том, что если я решу полностью удалить компонент GreetButton, мне не нужно будет отслеживать все методы, которые он использует, определенные в других компонентах.
Есть ли способ достичь этого?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я бы сказал, что метод updateGreetделает имеет отношение к App, поскольку он манипулирует App состоянием.
Я не рассматриваю это как проблему, зависящую от контекста, а скорее как обычную практику реагирования на передачу функций дочерним компонентам.
Чтобы выполнить свое желание, вы мог связываете и передаете метод AppsetState провайдеру, а затем реализуете updateGreet в компоненте GreetButton, но это было бы анти-шаблоном, и я бы не рекомендовал его.
Когда я работаю с Context API, я обычно определяю свой контекст в отдельном файле и реализую собственный провайдер в соответствии со своими потребностями, передавая связанные методы и свойства вниз и используя их по всему дереву по мере необходимости.
По сути, реализуйте то, что у вас есть в App, как собственный класс ПровайдерGreetProvider. В методе рендеринга для GreetProvider просто передайте дочерние элементы:
render() {
return (
<DataContext.Provider value = { this.state }>
{ this.props.children }
</DataContext.Provider>
)
}
Теперь вся ваша логика приветствия может жить вместе в источнике с контекстом. Используйте свой новый класс GreetProvider в App, и любой из его дочерних элементов сможет использовать его методы.
Вы можете передать
setStateи определить методы где угодно (вау - вы можете расширять возможности на лету) ... но, вероятно, вы не знаете, для чего предназначен контекст.