Ошибка в ReactJS: Компонент изменяет неконтролируемый текстовый ввод на контролируемый
Описание проблемы:
При использовании моего компонента я столкнулся с предупреждением:
Warning: A component is changing an uncontrolled input of type text to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component.
Проблема возникает при работе с текстовым полем input в методе render
. Я использую состояние для управления значением поля, но в некоторых случаях значение this.state.fields["name"]
может быть undefined
, что приводит к тому, что React рассматривает это поле как неконтролируемое.
Вот мой код:
constructor(props) {
super(props);
this.state = {
fields: {},
errors: {}
}
this.onSubmit = this.onSubmit.bind(this);
}
onChange(field, e) {
let fields = this.state.fields;
fields[field] = e.target.value;
this.setState({ fields });
}
render() {
return(
<div className="form-group">
<input
value={this.state.fields["name"]}
onChange={this.onChange.bind(this, "name")}
className="form-control"
type="text"
refs="name"
placeholder="Name *"
/>
<span style={{color: "red"}}>{this.state.errors["name"]}</span>
</div>
)
}
Как я могу исправить эту проблему, чтобы избежать предупреждения и гарантировать, что поле ввода всегда будет контролируемым?
5 ответ(ов)
Чтобы разместить текстовое поле внутри компонента, используйте следующий код:
<input
className="class-name"
type="text"
id="id-123"
value={this.state.value || ""}
name="field-name"
placeholder="Введите имя"
/>
Здесь мы добавили атрибуты, которые позволяют задавать класс, тип, идентификатор, значение, имя поля и текст подсказки для ввода. Не забудьте, что значение this.state.value
должно быть предварительно определено в вашем состоянии компонента.
В дополнение к принятому ответу, если вы используете элемент input
типа checkbox
или radio
, я обнаружил, что мне необходимо проверять атрибут checked
на null
или undefined
.
<input
id={myId}
name={myName}
type="checkbox" // или "radio"
value={myStateValue || ''}
checked={someBoolean ? someBoolean : false}
/>
Если вы используете TypeScript (или Babel), вы можете воспользоваться нулевым слиянием вместо логического оператора ИЛИ:
value={myStateValue ?? ''}
checked={someBoolean ?? false}
Таким образом, вы избежите потенциальных проблем с неопределёнными значениями.
Простыми словами, вы должны сначала задать начальное состояние.
Если вы не установите начальное состояние, React будет считать это неконтролируемым компонентом.
Это происходит потому, что значение не может быть undefined или null. Чтобы решить эту проблему, вы можете сделать так:
value={ this.state.value ?? "" }
Здесь используем оператор нулевого слияния (??), который вернёт пустую строку, если this.state.value
равно undefined
или null
.
Ошибка возникает из-за того, что при использовании const [name, setName] = useState()
вы инициализируете состояние name
как undefined
, что может вызвать проблему при попытке использовать это значение в текстовом поле.
Когда вы изменяете строку на const [name, setName] = useState('')
, вы инициализируете состояние name
как пустую строку. Это решает проблему, так как теперь name
всегда будет строкой, и ваше текстовое поле сможет корректно обработать ввод.
Такой подход предпочтителен, когда вы хотите избежать ошибок, связанных с undefined
, и гарантировать, что состояние всегда будет строкового типа.
Как программно выполнять навигацию с помощью React Router?
Как условно добавлять атрибуты к компонентам React?
Как установить фокус на поле ввода после рендеринга?
Метод set в useState не отражает изменения немедленно
В чем разница между React Native и React?