Я пытаюсь найти правильный способ определить некоторые компоненты, которые могут быть использованы в общем виде:
<Parent>
<Child value="1">
<Child value="2">
</Parent>
Существует логика для рендеринга между родительскими и дочерними компонентами, конечно, вы можете себе представить <select>
и <option>
в качестве примера этой логики.
Это фиктивная реализация для цели вопроса:
var Parent = React.createClass({
doSomething: function(value) {
},
render: function() {
return (<div>{this.props.children}</div>);
}
});
var Child = React.createClass({
onClick: function() {
this.props.doSomething(this.props.value); // doSomething is undefined
},
render: function() {
return (<div onClick={this.onClick}></div>);
}
});
Вопрос в том, когда вы используете {this.props.children}
для определения компонента-оболочки, как вы передаете какое-то свойство всем его дочерним элементам?
Ответы:
Клонирование детей с новыми реквизитами
Вы можете использовать React.Children для перебора дочерних элементов, а затем клонировать каждый элемент с помощью нового реквизита (с мелким слиянием ), используя React.cloneElement, например:
Скрипка: https://jsfiddle.net/2q294y43/2/
Вызов детей как функция
Вы также можете передать реквизит детям с помощью реквизита . В этом подходе дочерние элементы (которые могут быть
children
или любым другим именем проп) - это функция, которая может принимать любые аргументы, которые вы хотите передать, и возвращает дочерние элементы:Вместо
<React.Fragment>
или просто<>
вы также можете вернуть массив, если хотите.Скрипка: https://jsfiddle.net/ferahl/y5pcua68/7/
источник
value
переданныйdoSomething
теряется.Для немного более чистого способа сделать это, попробуйте:
Редактировать: Вы можете использовать с несколькими отдельными дочерними элементами (дочерний элемент должен быть компонентом). Протестировано в 16.8.6
источник
this.props.children
)cloneElement
..., которая ожидает ... элемент.React.Children.only
функция возвращает единственного потомка или выдает исключение, если их несколько (этого не было бы, если бы не было варианта использования).Попробуй это
У меня это сработало с использованием response-15.1.
источник
React.cloneElement()
напрямую, не окружая его<div>
тегами? Что, если дочерний элемент<span>
(или что-то еще) и мы хотим сохранить его тип элемента тега?React.cloneElement(React.Children.only(this.props.children), {...this.props})
что приведет к ошибке, если будет передано более одного дочернего элемента. Тогда вам не нужно заключать в div.let {children, ...acyclicalProps} = this.props
и потомReact.cloneElement(React.Children.only(children), acyclicalProps)
.Передайте реквизит, чтобы направить детей.
Посмотреть все остальные ответы
Передача общих глобальных данных через дерево компонентов через контекст
Отказ от ответственности: это обновленный ответ, предыдущий использовал старый контекстный API
Он основан на принципе Потребитель / Обеспечить. Сначала создайте свой контекст
Тогда используйте через
а также
Полный пример, полупсевдокод.
1 https://facebook.github.io/react/docs/context.html
источник
this.context
) - он волшебным образом не сливал контекст с реквизитом. Вы должны были намеренно установить и использовать контекст, а это совсем другое.Передача реквизита вложенным детям
С обновлением до React 16.6 теперь вы можете использовать React.createContext и contextType .
источник
this
контекстаВы можете использовать
React.cloneElement
, лучше узнать, как это работает, прежде чем начать использовать его в своем приложении. Это введено вReact v0.13
, читайте дальше для получения дополнительной информации, так что кое-что вместе с этой работой для вас:Итак, приведите строки из документации React, чтобы вы могли понять, как все это работает и как их использовать:
больше здесь ...
источник
Лучший способ, который позволяет вам передавать свойства, это
children
как функцияПример:
источник
nested components
. У React нет вложенных шаблонов, только композиции. Да, дети должны быть функцией, никаких конфликтов нет, потому что это действительный JSX-ребенок. Можете ли вы привести пример сnesting components
?<Parent>{props => <Nest><ChildComponent /></Nest>}</Parent>
вместо (не работает),<Parent><Nest>{props => <ChildComponent />}</Nest></Parent>
поэтому я согласен, что это лучший ответTypeError: children is not a function
Мне нужно исправить общепринятый ответ выше , чтобы заставить его работать , используя , что вместо этого указателя. В рамках функции карты не определена функция doSomething .
Обновление: это исправление для ECMAScript 5, в ES6 нет необходимости в var that = this
источник
bind()
doSomething
doSomething: function(obj) { console.log(obj) }
this.props.doSomething(obj)
"obj"
apply
метод. использованиеbind()
в функции рендеринга будет создавать новую функцию каждый раз, когда вызывается метод рендеринга.Более чистый способ с учетом одного или нескольких детей
источник
this.props
. В общем, я бы рекомендовал клонировать только с определенными реквизитами, а не со всем.{...this.props}
не работает для меня,{...child.props}
правильный путь ?React.Children.map(children, child => React.cloneElement(child, props))
Ни один из ответов не решает проблему наличия дочерних элементов, которые НЕ являются компонентами React, такими как текстовые строки. Обходной путь может быть что-то вроде этого:
источник
Вам больше не нужно
{this.props.children}
. Теперь вы можете обернуть свой дочерний компонент с помощьюrender
inRoute
и передать свой реквизит как обычно:источник
Parent.jsx:
Child.jsx:
и main.jsx:
см. пример здесь: https://plnkr.co/edit/jJHQECrKRrtKlKYRpIWl?p=preview
источник
Может быть, вы также найдете полезную эту функцию, хотя многие люди считают, что это анти-шаблон, но его все еще можно использовать, если вы знаете, что делаете, и хорошо разрабатываете свое решение.
Функция в качестве дочерних компонентов
источник
Если у вас есть несколько детей, которым вы хотите передать реквизиты , вы можете сделать это следующим образом, используя React.Children.map:
Если у вашего компонента есть только один дочерний элемент, нет необходимости в отображении, вы можете сразу же cloneElement:
источник
Согласно документации
cloneElement()
Таким образом, cloneElement - это то, что вы бы использовали для предоставления пользовательских реквизитов детям. Тем не менее, в компоненте может быть несколько дочерних элементов, и вам нужно будет зациклить его. Что другие ответы предлагают для вас, чтобы отобразить их, используя
React.Children.map
. Однако вReact.Children.map
отличие отReact.cloneElement
изменений ключи элемента добавляются и добавляются.$
в качестве префикса. Проверьте этот вопрос для более подробной информации: React.cloneElement внутри React.Children.map вызывает изменение ключей элементаЕсли вы хотите избежать этого, вы должны вместо этого перейти к
forEach
функции, какисточник
В дополнение к ответу @and_rest, я клонирую детей и добавляю класс.
источник
Я думаю, что опора рендеринга является подходящим способом справиться с этим сценарием
Вы позволяете Родителю предоставлять необходимые реквизиты, используемые в дочернем компоненте, путем рефакторинга Родительского кода, чтобы выглядеть примерно так:
Затем в дочернем компоненте вы можете получить доступ к функции, предоставленной родителем следующим образом:
Теперь структура fianl будет выглядеть так:
источник
Способ 1 - клонирование детей
Способ 2 - использовать составной контекст
Контекст позволяет вам передавать реквизит глубокому дочернему компоненту без явной передачи его в качестве реквизита между компонентами между ними.
Контекст имеет недостатки:
Использование компонуемого контекста
источник
{children}:{children:ReactNode}
?"children"
имеет типReactNode
Самый лучший способ сделать это:
источник
Любой, у кого есть единственный дочерний элемент, должен это сделать.
источник
Это то, что вам нужно?
источник
Почему-то React.children не работал для меня. Это то, что сработало для меня.
Я хотел просто добавить класс для ребенка. похоже на изменение реквизита
Хитрость здесь - это React.cloneElement . Вы можете передать любую опору подобным образом
источник
Render реквизит является наиболее точным подходом к этой проблеме. Вместо того чтобы передавать дочерний компонент в родительский компонент в качестве дочерних компонентов, позвольте родительскому компоненту визуализировать дочерний компонент вручную. Render - это встроенный реквизит в реакции, который принимает параметр функции. В этой функции вы можете позволить родительскому компоненту отображать все, что вы хотите с пользовательскими параметрами. По сути, он делает то же самое, что и дочерний реквизит, но он более настраиваемый.
Пример на codepen
источник
При использовании функциональных компонентов часто
TypeError: Cannot add property myNewProp, object is not extensible
возникает ошибка при попытке установить новые свойстваprops.children
. Для этого есть обходной путь: клонирование реквизита, а затем клонирование самого ребенка с помощью нового реквизита.источник