Я реализую вложенный компонент, и все мои компоненты должны иметь опору Переменная, теперь у меня есть:
<Parent variable = "myVariable">
<Child1 variable = "myVariable" />
<Child2 variable = "myVariable" />
</Parent>
Но я не хочу передавать опору напрямую каждому компоненту, и мне нужно что-то вроде этого:
<Parent variable = "myVariable">
<Child1 />
<Child2 />
</Parent>
и мне нужно получить доступ к переменная опора из Ребенок1 и Ребенок2.
Вы можете попробовать Компонент высшего порядка
Вы также можете изучить контекст, который больше не является экспериментальным.



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


Вы можете передать детей в качестве реквизита для родительского элемента:
class Wrapper extends React.Component {
render() {
return (
this.props.wraps.map(El => <El {...this.props} />);
};
}
}
Итак, вы можете:
<Wrapper wraps = {[Child1, Child2]} variable = "whatever" />
На самом деле мне нужно сохранить структуру DOM
Для этого есть два решения. Использование React.createContext или React.cloneElement в родительском компоненте.
I highly recommend using React.createContext in React 16.3+ since this is exactly what React Context is meant for. Its also especially helpful if you have flow to keep
proptype checking working properly.Note in React 16.6 its even easier to use context by using contextType.
https://reactjs.org/docs/context.html
(или используя create-response-context https://github.com/jamiebuilds/create-react-context), если вы не в курсе.
// parentFile.js
import * as React from 'react';
export const MyContext = React.createContext(); // React.createContext accepts a defaultValue as the first param
type Props = {
variable: string,
children: React.Node
};
class Parent extends React.Component<Props> {
render() {
return (
<MyContext.Provider value = {{ variable: this.props.variable }}>
{this.props.children}
</MyContext.Provider>
);
}
}
class Child1 extends Component<{}> {
static contextType = MyContext;
render() {
return (<div>{this.context.variable}</div>);
}
}
// IF you have a child in a different file make sure you import the correct consumer
// child2.js
import * as React from 'react';
import { MyContext } from './parentFile';
class Child2 extends Component<{}> {
static contextType = MyContext;
render() {
return (<span>{this.context.variable}</span>);
}
}
React.createContext сияет здесь, где вы можете обрабатывать вложенные компоненты
// Example of using Parent and Child
import * as React from 'react';
class SomeComponent extends React.Component<{}> {
render() {
<Parent variable = "test">
<Child1 />
{ /* Previously you couldn't use
React.cloneElement to handle the nested case */ }
<SomeOtherComp>
<Child2 />
</SomeOtherComp>
</Parent>
}
}
This is a quick example of how to do this without React Context and using React.cloneElement
import * as React from 'react';
class Parent extends Component {
render() {
const { children, props } = this.props;
return (
React.Children.map(children, child =>
React.cloneElement(child, {...props})
)
);
}
}
не могли бы вы привести пример jsx?
Именно для этого и был разработан createContext . Другой вариант - использовать Redux для обработки информации, но это серьезное обязательство, если вы еще не внедрили Redux в свое приложение.
@KennethTruong Что делать, если у нас есть динамический дочерний компонент? Например, я хочу иметь компонент AnotherChild. Должен ли я добавить еще один ChildConsumer для этого компонента? Потому что я упомянул <Child1 /> и <Child2 />. но в этом примере я вижу только <Child /> На самом деле я хочу получить доступ к переменной в каждом дочернем компоненте, а не только в <Child />
Собственно, подумав об этом. Если у вас есть динамический дочерний элемент, вам придется добавить ChildConsumer во все дочерние компоненты. Или вы всегда можете использовать мое второе решение, которое должно работать с динамическими детьми.
Другой вариант для динамических компонентов - добавить React.Element в реквизиты, но я рекомендую просто использовать ChildConsumer для любых дочерних компонентов, которые в нем нуждаются.
Да, ReactContext может использоваться вложенными компонентами! Просто используйте тот же ContextConsumer
Я обновил свой пример, чтобы показать Child1, Child2 и NestedComponent. Позвольте мне знать, если это помогает
Что делать, если Child1 и Child2 находятся в разных файлах? Все примеры, которые я вижу, предполагают, что они находятся в одном файле. У меня возникают проблемы с тем, чтобы это работало, когда дети находятся в других файлах.
@jamesemanon, если дети находятся в разных файлах. Вы должны убедиться, что экспортируете ChildConsumer и импортируете его в разные дочерние файлы.
// parentFile.js const {Provider, Consumer} из React.createContext (); экспорт const SomeConsumer = Consumer; // Импорт дочернего файла 1 {SomeConsumer} из 'parentFile'; // Импорт дочернего файла 2 {SomeConsumer} из 'parentFile';
да, я закончил идти этим маршрутом, но это так .... мля. Можно было бы создать своего собственного подписчика (pub / sub), и это, кажется, одно и то же, верно? Итак, для каждого использования createContext у нас должен быть отдельный файл для его экспорта? Кажется инвазивным? нет?
Если бы вы создали свой собственный pub / sub, у вас было бы больше шаблонного кода. (Поскольку вам нужно вызвать setState и т. д. И сделать pub / sub частью жизненного цикла React. Хотя это будет автоматически отображаться, когда поставщик изменяет значение.)
Возможно, может помочь реализация Parent как HoC, который передает опору своим детям?