it-swarm.com.ru

React - изменение неконтролируемого ввода

У меня есть простой компонент реагирования с формой, которая, как мне кажется, имеет один контролируемый вход:

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.

238
alexs333

Я считаю, что мой вклад контролируется, поскольку он имеет ценность.

Для входа, который необходимо контролировать, его значение должно соответствовать значению переменной состояния.

Это условие изначально не выполняется в вашем примере, потому что this.state.name изначально не установлен. Поэтому вход изначально не контролируется. Как только обработчик onChange запускается в первый раз, устанавливается this.state.name. В этот момент вышеуказанное условие удовлетворяется, и вход считается контролируемым. Этот переход от неконтролируемого к управляемому производит ошибку, замеченную выше.

Путем инициализации this.state.name в конструкторе:

например.

this.state = { name: '' };

вход будет контролироваться с самого начала, устраняя проблему. См. Реагировать управляемые компоненты для большего количества примеров.

Независимо от этой ошибки, у вас должен быть только один экспорт по умолчанию. Ваш код выше имеет два.

278
fvgs

Когда вы впервые визуализируете свой компонент, this.state.name не установлен, поэтому он оценивается как undefined, и в итоге вы передаете value={undefined} вашей input.

Когда ReactDOM проверяет, контролируется ли поле, он проверяет, является ли value != null (обратите внимание, что это !=, а не !==), и, поскольку undefined == null в JavaScript, он решает, что оно неуправляемо.

Таким образом, когда вызывается onFieldChange(), для this.state.name устанавливается строковое значение, ваш ввод из неконтролируемого становится управляемым.

Если вы сделаете this.state = {name: ''} в своем конструкторе, потому что '' != null, ваш ввод будет иметь значение все время, и это сообщение исчезнет.

84
Adam Brenecki

Другим подходом может быть установка значения по умолчанию внутри вашего ввода, например:

 <input name="name" type="text" value={this.state.name || ''} onChange={this.onFieldChange('name').bind(this)}/>
28
JpCrow

Я знаю, что другие уже ответили на это. Но один из очень важных факторов, который может помочь другим людям, испытывающим подобные проблемы:

Вам необходимо добавить обработчик onChange в поле ввода (например, textField, checkbox, radio и т.д.). И всегда обрабатывать действия через обработчик onChange, например: 

<input ... onChange={ this.myChangeHandler} ... />

и когда вы работаете с checkbox, вам может потребоваться обработать его состояние checked с помощью !!, например:

<input type="checkbox" checked={!!this.state.someValue} onChange={.....} >

Ссылка: https://github.com/facebook/react/issues/6779#issuecomment-326314716

6
Muhammad Hannan

Один потенциальный недостаток при установке значения поля "" (пустая строка) в конструкторе - это если поле является необязательным и оставлено неотредактированным. Если вы не сделаете некоторый массаж перед публикацией формы, поле будет сохранено в вашем хранилище данных в виде пустой строки вместо NULL. 

Эта альтернатива позволит избежать пустых строк:

constructor(props) {
    super(props);
    this.state = {
        name: null
    }
}

... 

<input name="name" type="text" value={this.state.name || ''}/>
4
Greg R Taylor

Когда вы используетеonChange={this.onFieldChange('name').bind(this)}во входных данных, вы должны объявить пустую строку вашего состояния как значение поля свойства.

неверный путь:

this.state ={
       fields: {},
       errors: {},
       disabled : false
    }

правильный путь:

this.state ={
       fields: {
         name:'',
         email: '',
         message: ''
       },
       errors: {},
       disabled : false
    }
3
KARTHIKEYAN.A

Если реквизиты вашего компонента были переданы как состояние, установите значение по умолчанию для ваших входных тегов.

<input type="text" placeholder={object.property} value={object.property ? object.property : ""}>
2
Emperor Krauser

Установите значение для свойства name в начальном состоянии.

this.state={ name:''};

1
lakmalsathyajith

В моем случае я упустил что-то действительно тривиальное. 

<input value={state.myObject.inputValue} />

Мое состояние было следующим, когда я получал предупреждение:

state = {
   myObject: undefined
}

Чередуя мое состояние с ссылаясь на ввод моего значения , моя проблема была решена:

state = {
   myObject: {
      inputValue: ''
   }
}
1
Menelaos Kotsollaris

Простое решение для решения этой проблемы - установить пустое значение по умолчанию:

<input name='myInput' value={this.state.myInput || ''} onChange={this.handleChange} />
0
MUSTAPHA GHLISSI

Обычно это происходит только в том случае, если вы не контролируете значение поля, когда приложение запускается, и после того, как какое-то событие или какая-либо функция сработали или состояние изменилось, вы теперь пытаетесь контролировать значение в поле ввода. 

Этот переход отсутствия контроля над входом и последующего контроля над ним - вот что в первую очередь вызывает проблему.

Лучший способ избежать этого - объявить некоторое значение для ввода в конструкторе компонента. Так что элемент input имеет значение с самого начала приложения. 

0
Ashish Nandan Singh