У меня есть два компонента.
- Родительский компонент
- Дочерний компонент
Я пытался вызвать метод ребенка из Parent, я пытался таким образом, но не смог получить результат
class Parent extends Component {
render() {
return (
<Child>
<button onClick={Child.getAlert()}>Click</button>
</Child>
);
}
}
class Child extends Component {
getAlert() {
alert('clicked');
}
render() {
return (
<h1 ref="hello">Hello</h1>
);
}
}
Есть ли способ вызвать метод ребенка от родителя?
Примечание. Дочерний и родительский компоненты находятся в двух разных файлах.
javascript
reactjs
N8FURY
источник
источник
Ответы:
Прежде всего, позвольте мне выразить, что это вообще не тот способ, которым можно заниматься в React Land. Обычно вы хотите передать функциональность дочерним элементам в подпорках и передать уведомления от дочерних элементов в событиях (или еще лучше:)
dispatch
.Но если вам необходимо предоставить обязательный метод для дочернего компонента, вы можете использовать ссылки . Помните, что это аварийный люк, который обычно указывает на лучший дизайн.
Использование хуков и функциональных компонентов (
>= react@16.8
)Документация
useImperativeHandle()
находится здесь :Использование компонентов класса (
>= react@16.4
)Устаревший API (
<= react@16.3
)Для исторических целей, вот стиль на основе обратного вызова, который вы бы использовали с версиями React до 16.3:
источник
connect
возвращает компонент более высокого порядка, который оборачивает ваш оригинальный экземпляр.getWrappedInstance()
Сначала вам нужно вызвать подключенный компонент, чтобы получить исходный компонент. Затем вы можете вызвать методы экземпляра на этом.componentWillReceiveProps
, и использовать его в качестве триггера.Вы можете использовать другой шаблон здесь:
Что он делает, так это устанавливает метод родителя
clickChild
при монтировании child. Таким образом, когда вы нажимаете кнопку в родительском, он будет вызывать,clickChild
который вызывает ребенкаgetAlert
.Это также работает, если ваш ребенок обернут,
connect()
так что вам не нуженgetWrappedInstance()
взлом.Обратите внимание, что вы не можете использовать
onClick={this.clickChild}
в родительском, потому что когда родительский отображается, дочерний не подключен, поэтомуthis.clickChild
еще не назначен. ИспользованиеonClick={() => this.clickChild()}
хорошо, потому что при нажатии кнопкиthis.clickChild
уже должны быть назначены.источник
_this2.clickChild is not a function
почему?https://facebook.github.io/react/tips/expose-component-functions.html для получения дополнительных ответов см. здесь Вызов методов на дочерних компонентах React
Изучая ссылки на компонент «причина», вы нарушаете инкапсуляцию и делаете невозможным рефакторинг этого компонента без тщательного изучения всех мест его использования. По этой причине мы настоятельно рекомендуем рассматривать ссылки как частные для компонента, так же как и для состояния.
В общем, данные должны передаваться по дереву через реквизит. Есть несколько исключений из этого (например, вызов .focus () или запуск одноразовой анимации, которая на самом деле не «меняет» состояние), но каждый раз, когда вы выставляете метод с именем «set», реквизит обычно лучший выбор. Постарайтесь сделать так, чтобы внутренний компонент ввода беспокоился о своем размере и внешнем виде, чтобы никто из его предков не беспокоился.
источник
Альтернативный метод с useEffect:
родитель:
Дети:
источник
Мы можем использовать ссылки другим способом, так как
Мы собираемся создать родительский элемент, он будет визуализировать
<Child/>
компонент. Как видите, для компонента, который будет отображаться, нужно добавить атрибут ref и указать для него имя.Затем
triggerChildAlert
функция, расположенная в родительском классе, получит доступ к свойству refs этого контекста (когдаtriggerChildAlert
функция сработает, она получит доступ к дочерней ссылке и будет иметь все функции дочернего элемента).Теперь дочерний компонент, как теоретически разработано ранее, будет выглядеть так:
Здесь исходный код -
Надежда поможет вам!
источник
Если вы делаете это просто потому, что хотите, чтобы Ребенок предоставил своим родителям повторно используемую черту, то вы можете подумать об этом, используя render-props вместо этого .
Эта техника фактически переворачивает конструкцию с ног на голову.
Child
Теперь оборачивает родитель, поэтому я переименовал егоAlertTrait
ниже. Я сохранил названиеParent
для преемственности, хотя сейчас это не совсем родитель.В этом случае AlertTrait предоставляет одну или несколько черт, которые он передает в качестве реквизита для любого компонента, который ему был дан в его
renderComponent
реквизите.Родитель получает
doAlert
в качестве опоры и может вызывать ее при необходимости.(Для ясности я назвал опору
renderComponent
в вышеприведенном примере. Но в связанных с React документах они просто называют этоrender
.)Компонент Trait может отображать вещи, окружающие Parent, в своей функции render, но он ничего не отображает внутри родительского элемента. На самом деле это может сделать вещи внутри Родителя, если он прошел другую опору (например,
renderChild
) родительскому объекту, который родительский объект мог бы затем использовать во время своего метода render.Это несколько отличается от того, о чем просил OP, но некоторые люди могут оказаться здесь (как мы), потому что они хотели создать черту многократного использования и думали, что дочерний компонент - хороший способ сделать это.
источник
this.clickChild = click
но ваши несколько секундомеров будут передавать несколько функций, поэтому вам нужно будет сохранить все из них:this.watchRestartFuncs[watchId] = restartWatch
Вы можете легко достичь этого
Steps-
Из дочернего компонента обращайтесь к этой переменной с помощью props и выполняйте нужный метод, используя условие if.
источник
Я использую
useEffect
ловушку, чтобы преодолеть головную боль при выполнении всего этого, поэтому теперь я передаю переменную child так:источник
Я не был удовлетворен ни одним из решений, представленных здесь. На самом деле существует очень простое решение, которое может быть сделано с использованием чистого Javascript, не полагаясь на некоторые функциональные возможности React, кроме базового объекта props, и дает вам преимущество общения в любом направлении (parent -> child, child -> parent). Вам необходимо передать объект из родительского компонента в дочерний компонент. Этот объект - это то, что я называю «двунаправленной ссылкой» или для краткости biRef. По сути, объект содержит ссылку на методы в родительском объекте, которые родитель хочет предоставить. И дочерний компонент присоединяет методы к объекту, который родитель может вызвать. Что-то вроде этого:
Другое преимущество этого решения заключается в том, что вы можете добавить намного больше функций в родительский и дочерний процесс, передавая их от родительского к дочернему элементу, используя только одно свойство.
Улучшение по сравнению с приведенным выше кодом заключается в том, что родительские и дочерние функции добавляются не непосредственно к объекту biRef, а к подчиненным элементам. Родительские функции должны быть добавлены к члену с именем «parent», тогда как дочерние функции должны быть добавлены к члену с именем «child».
Размещая родительские и дочерние функции в отдельных членах объекта biRef, вы получите четкое разделение между ними и легко увидите, какие из них принадлежат родительскому или дочернему объекту. Это также помогает предотвратить случайную перезапись дочерним компонентом родительской функции, если одна и та же функция появляется в обеих.
И последнее: если вы заметите, родительский компонент создает объект biRef с помощью var, тогда как дочерний компонент обращается к нему через объект props. Может быть соблазнительно не определять объект biRef в родительском объекте и обращаться к нему от его родительского объекта через собственный параметр props (что может иметь место в иерархии элементов пользовательского интерфейса). Это рискованно, потому что ребенок может подумать, что функция, которую он вызывает у родителя, принадлежит родителю, когда он на самом деле может принадлежать дедушке. В этом нет ничего плохого, если вы знаете об этом. Если у вас нет причин для поддержки какой-либо иерархии, выходящей за рамки родительских и дочерних отношений, лучше всего создать biRef в родительском компоненте.
источник
Вы можете сделать Inveritance Inversion (посмотрите его здесь: https://medium.com/@franleplant/react-higher-order-components-in-depth-cf9032ee6c3e ). Таким образом, у вас есть доступ к экземпляру компонента, который вы хотите обернуть (таким образом, вы сможете получить доступ к его функциям)
источник
Я думаю, что самый простой способ вызова методов - это установить запрос на дочерний компонент. Затем, как только ребенок обрабатывает запрос, он вызывает метод обратного вызова для сброса запроса.
Механизм сброса необходим, чтобы иметь возможность отправлять один и тот же запрос несколько раз друг за другом.
В родительском компоненте
В методе рендеринга родителя:
Родителю нужно 2 метода, чтобы общаться с ребенком в 2 направлениях.
В дочернем компоненте
Ребенок обновляет свое внутреннее состояние, копируя запрос из реквизита.
Затем, наконец, он обрабатывает запрос и отправляет сброс родителю:
источник
Еще один способ вызвать дочернюю функцию из родительского - использовать
componentDidUpdate
функцию в дочернем компоненте. Я передаю реквизитtriggerChildFunc
от Родителя Ребенку, который изначально естьnull
. Значение изменяется на функцию при нажатии кнопки, и дочерний элемент замечает, что он изменяется,componentDidUpdate
и вызывает свою собственную внутреннюю функцию.Поскольку prop
triggerChildFunc
изменяется на функцию, мы также получаем обратный вызов для Parent. Если Parent не нужно знать, когда вызывается функция, значениеtriggerChildFunc
может, например, измениться сnull
наtrue
вместо.CodePen: https://codepen.io/calsal/pen/NWPxbJv?editors=1010
источник
Вот мое демо: https://stackblitz.com/edit/react-dgz1ee?file=styles.css
Я использую
useEffect
для вызова методов дочернего компонента. Я пытался с,Proxy and Setter_Getter
ноuseEffect
кажется, что гораздо более удобный способ вызова дочернего метода из родительского. Чтобы использоватьProxy and Setter_Getter
это, кажется, есть некоторая тонкость, которую нужно преодолеть в первую очередь, потому что элемент, представленный первым, является элементом objectLike черезref.current return => <div/>
специфику. Что касаетсяuseEffect
, вы также можете использовать этот подход для установки состояния родителя в зависимости от того, что вы хотите делать с детьми.В предоставленной мною демонстрационной ссылке вы найдете мой полный код ReactJS с моим черновиком внутри, чтобы вы могли оценить рабочий процесс моего решения.
Здесь я предоставляю вам свой фрагмент кода ReactJS только с соответствующим кодом. :
источник
Мы счастливы с пользовательским крючком, который мы называем
useCounterKey
. Он просто устанавливает counterKey или ключ, который отсчитывает от нуля. Функция, которую она возвращает, сбрасывает ключ (то есть увеличивает). (Я считаю, что это самый идиоматичный способ сброса компонента в React - просто нажмите клавишу).Однако этот хук также работает в любой ситуации, когда вы хотите отправить одноразовое сообщение клиенту, чтобы что-то сделать. Например, мы используем его, чтобы сфокусировать элемент управления в дочернем элементе на определенном родительском событии - он просто автоматически фокусируется при каждом обновлении ключа. (Если требуется больше реквизита, их можно установить до сброса ключа, чтобы они были доступны при возникновении события.)
Этот метод имеет некоторую кривую обучения, поскольку он не так прост, как типичный обработчик событий, но кажется наиболее идиоматичным способом обработки этого в React, который мы нашли (поскольку ключи уже функционируют таким образом). Def открыт для отзывов об этом методе, но он работает хорошо!
Примеры использования:
( Благодарим Кента Доддса за концепцию counterKey .)
источник
Вот ошибка? на что обратить внимание: я согласен с решением Россипедии, используя forwardRef, useRef, useImperativeHandle
В Интернете есть некоторая дезинформация о том, что ссылки могут создаваться только из компонентов класса React, но вы действительно можете использовать функциональные компоненты, если используете вышеупомянутые хуки выше. Обратите внимание, что ловушки работали для меня только после того, как я изменил файл, чтобы не использовать withRouter () при экспорте компонента. Т.е. изменение от
вместо того, чтобы быть
Оглядываясь назад, метод withRouter () в любом случае не нужен для такого компонента, но обычно он ничем не мешает. В моем случае я создал компонент для создания таблицы, предназначенной для просмотра и редактирования значений конфигурации, и я хотел, чтобы этот дочерний компонент мог сбросить значения своего состояния при каждом нажатии кнопки «Сброс» родительской формы. UseRef () не получал должным образом ref или ref.current (продолжал получать значение null), пока я не удалил withRouter () из файла, содержащего мой дочерний компонент TableConfig
источник