У меня есть простой компонент реакции с формой, которая, как я полагаю, имеет один управляемый вход:
import React from 'react';
export default class MyForm extends React.Component {
constructor(props) {
super(props);
this.state = {}
}
render() {
return (
<form className="add-support-staff-form">
<input name="name" type="text" value={this.state.name} onChange={this.onFieldChange('name').bind(this)}/>
</form>
)
}
onFieldChange(fieldName) {
return function (event) {
this.setState({[fieldName]: event.target.value});
}
}
}
export default MyForm;
Когда я запускаю свое приложение, я получаю следующее предупреждение:
Внимание: MyForm меняет неконтролируемый ввод текста типа, который будет контролируется. Элементы ввода не должны переключаться с неконтролируемого на (или наоборот). Решите, используя неконтролируемый входной элемент для времени жизни компонента
Я считаю, что мой вход контролируется, поскольку он имеет значение. Мне интересно, что я делаю неправильно?
Я использую React 15.1.0
Я считаю, что мой вход управляется, поскольку он имеет значение.
Для управляемого входа его значение должно соответствовать значению переменной состояния.
Это условие изначально не встречается в вашем примере, потому что this.state.name
изначально не задано. Следовательно, вход изначально неконтролируемый. Как только обработчик onChange
запускается в первый раз, устанавливается this.state.name
. В этот момент указанное условие выполняется, и ввод считается контролируемым. Этот переход от неконтролируемого к контролируемому приводит к ошибке, наблюдаемой выше.
Инициализируя this.state.name
в конструкторе:
например.
this.state = { name: '' };
вход будет управляться с самого начала, фиксируя проблему. Подробнее см. "Реагировать контролируемые компоненты" .
Не связанная с этой ошибкой, вы должны иметь только один экспорт по умолчанию. Ваш код выше имеет два.
Когда вы сначала визуализируете свой компонент, this.state.name
не установлен, поэтому он оценивается как undefined
, и вы заканчиваете передачу value={undefined}
на input
.
Когда ReactDOM проверяет, контролируется ли поле, проверяет, есть ли value != null
(обратите внимание, что это !=
, а не !==
), и поскольку undefined == null
в JavaScript, он решает, что он неконтролируемый.
Итак, когда вызывается onFieldChange()
, this.state.name
устанавливается в строковое значение, ваш вход переходит из неконтролируемого управления.
Если вы выполняете this.state = {name: ''}
в своем конструкторе, потому что '' != null
, ваш ввод будет иметь значение все время, и это сообщение исчезнет.
this.props.<whatever>
, что было проблемой с моей стороны. Спасибо, Адам!
render()
, или выражение в самом теге - все, что оценивается как undefined
. Рад, что смог помочь!
Другим подходом может быть установка значения по умолчанию внутри вашего ввода, например:
<input name="name" type="text" value={this.state.name || ''} onChange={this.onFieldChange('name').bind(this)}/>
Я знаю, что другие уже ответили на это. Но один из очень важных факторов здесь может помочь другим людям, испытывающим подобную проблему:
В поле ввода необходимо добавить обработчик onChange
(например, textField, флажок, радио и т.д.). И всегда обрабатывайте активность с помощью обработчика onChange
, например:
<input ... onChange={ this.myChangeHandler} ... />
и когда вы работаете с флажком, вам может потребоваться обработать его состояние checked
с помощью !!
, например:
<input type="checkbox" checked={!!this.state.someValue} onChange={.....} >
Ссылка: https://github.com/facebook/react/issues/6779#issuecomment-326314716
Когда вы используете onChange={this.onFieldChange('name').bind(this)}
во входных данных, вы должны объявить пустую строку вашего состояния в качестве значения поля свойства.
неверный путь:
this.state ={
fields: {},
errors: {},
disabled : false
}
правильный путь:
this.state ={
fields: {
name:'',
email: '',
message: ''
},
errors: {},
disabled : false
}
Один потенциальный недостаток при установке значения поля "" (пустая строка) в конструкторе - это если поле является необязательным и оставлено неотредактированным. Если вы не сделаете некоторый массаж перед отправкой формы, поле будет сохранено в вашем хранилище данных в виде пустой строки вместо NULL.
Эта альтернатива позволит избежать пустых строк:
constructor(props) {
super(props);
this.state = {
name: null
}
}
...
<input name="name" type="text" value={this.state.name || ''}/>
Установите значение для свойства name в начальном состоянии.
this.state={ name:''};
Если реквизиты вашего компонента были переданы как состояние, установите значение по умолчанию для ваших входных тегов.
<input type="text" placeholder={object.property} value={object.property ? object.property : ""}>
Обычно это происходит только в том случае, если вы не контролируете значение поля, когда приложение запускается, и после того, как какое-то событие или какая-либо функция сработали или состояние изменилось, вы теперь пытаетесь контролировать значение в поле ввода.
Этот переход отсутствия контроля над входом и последующего контроля над ним - вот что в первую очередь вызывает проблему.
Лучший способ избежать этого - объявить некоторое значение для ввода в конструкторе компонента. Так что элемент input имеет значение с самого начала приложения.
В моем случае я упустил что-то действительно тривиальное.
<input value={state.myObject.inputValue}/>
Мое состояние было следующим, когда я получал предупреждение:
state = {
myObject: undefined
}
Чередуя мое состояние со ссылкой на ввод моей стоимости, моя проблема была решена:
state = {
myObject: {
inputValue: ''
}
}
name={'question_groups.${questionItem.id}'}
?