Вызовите методы на дочерних компонентах React
Я хочу написать компонент Form, который может экспортировать метод для проверки его дочерних элементов. К сожалению, форма не "видит" какие-либо методы в своих дочерних элементах.
Вот как я определяю потенциальных детей формы:
var Input = React.createClass({
validate: function() {
...
},
});
И вот как я определяю класс Form:
var Form = React.createClass({
isValid: function() {
var valid = true;
this.props.children.forEach(function(component) {
// --> This iterates over all children that I pass
if (typeof component.validate === 'function') {
// --> code never reaches this point
component.validate();
valid = valid && component.isValid();
}
});
return valid;
}
});
Я заметил, что я могу вызвать метод для дочернего компонента, используя refs, но я не могу вызвать метод через props.children.
Есть ли причина для такого поведения React?
Как я могу это исправить?
2 ответа
Техническая причина заключается в том, что на момент попытки доступа к дочернему компоненту они еще не существуют (в DOM). Они еще не были установлены. Они были переданы вашему<Form>
компонент в качестве конструктора или метод в качестве класса реакции. (отсюда и название класса в React.createClass()
).
Как вы указываете, это можно обойти с помощью ссылок, но я бы не рекомендовал это. Во многих случаях ссылки, как правило, являются ярлыками для чего-то, для чего реакция не предназначена, и поэтому их следует избегать.
Вероятно, именно благодаря этой реакции родители затрудняют / делают невозможным доступ родителей к методам ребенка. Они не должны. Методы ребенка должны быть в ребенке, если они являются частными по отношению к ребенку: они делают что-то внутри ребенка, что не должно быть напрямую передано наверх к родителю. Если бы это было так, то обработка должна была быть сделана внутри родителя. Потому что родитель имеет по крайней мере всю информацию и данные, которые есть у ребенка.
Теперь, в вашем случае, я представляю, что у каждого входного (дочернего) компонента есть какой-то определенный метод проверки, который проверяет входное значение и, основываясь на результате, отправляет сообщение об ошибке. Скажем, красный контур вокруг неправильных полей.
Реакционным путем это может быть достигнуто следующим образом:
<Form>
компонент имеет состояние, которое включает в себяrunValidation
логическое значение.- как только
runValidation
установлен в true, внутриsetState( { runValidation: true });
Реакция автоматически перерисовывает всех детей. - если вы включите
runValidation
как опора для всех детей. - тогда каждый ребенок может проверить внутри своих
render()
функционировать с чем-то вродеif (this.props.runValidation) { this.validate() }
- который выполнит
validate()
функция у ребенка - функция validate может даже использовать состояние ребенка (состояние не изменяется при входе новых реквизитов) и использовать его для сообщения проверки (например, "пожалуйста, добавьте более сложные символы в свой пароль")
Теперь это еще не исправлено: вы можете захотеть провести некоторую проверку на уровне формы после того, как все дети подтвердят себя: например, когда все дети в порядке, отправьте форму.
Чтобы решить эту проблему, вы можете применить ярлык ссылки для окончательной проверки и отправки. И реализовать метод в вашем <Form>
внутри componentDidUpdate()
функция, чтобы проверить, если каждый ребенок в порядке (например, имеет зеленую рамку) И, если нажмите кнопку отправить, а затем отправить. Но, как правило, я настоятельно рекомендую не использовать ссылки.
Для окончательной проверки формы, лучший подход:
- добавьте переменную без состояния внутри вашего
<Form>
который содержит логические значения для каждого ребенка. Обратите внимание, что он должен быть не государственным, чтобы дети не могли запустить новый цикл рендеринга. - передать
validateForm
функционировать в качестве (обратного вызова) опоры для каждого ребенка. - внутри
validate()
в каждом ребенке звониthis.props.validateForm(someChildID)
который обновляет соответствующий логический параметр в переменной в форме. - в конце
validateForm
Функция в форме, проверьте, все ли логические значения верны, и если да, отправьте форму (или измените состояние формы или что-то еще).
Чтобы найти более продолжительное (и более сложное) решение для формирования валидации в реакции (с потоком), вы можете проверить эту статью.
Я не уверен, что что-то упустил, но, попробовав то, что предложил @wintvelt, я сталкивался с проблемой всякий раз, когда звонил runValidation
метод внутри метода рендеринга React, так как в моем случае runValidation
меняет состояние по телефону setState
в нем, таким образом, вызывая метод рендеринга, который, очевидно, является плохой практикой, так как метод рендеринга должен быть чистым, и если я положу runValidation
в willReceiveProps
это не будет вызвано в первый раз, потому что if
условие еще не выполнено (это условие изменяется в родительском компоненте с помощью setState
, но в первом звонке willReceiveProps
это все еще ложь).