Eu tenho um componente de reação simples com o formulário que acredito ter uma entrada controlada:
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;
Quando executo meu aplicativo, recebo o seguinte aviso:
Aviso: O MyForm está alterando uma entrada não controlada do tipo de texto a ser controlado. Os elementos de entrada não devem mudar de não controlado para controlado (ou vice-versa). Decida entre usar um elemento de entrada controlado ou não controlado durante a vida útil do componente
Acredito que minha entrada é controlada, pois tem um valor. Eu estou querendo saber o que estou fazendo de errado?
Estou usando o React 15.1.0
fonte
name={'question_groups.${questionItem.id}'}
?value
suporte tiver um valor não nulo / indefinido. O suporte não precisa corresponder a uma variável de estado (poderia ser apenas uma constante e o componente ainda seria considerado controlado). A resposta de Adam é mais correta e deve ser aceita.Quando você tornar o seu componente,
this.state.name
não está definido, por isso é avaliado comoundefined
ounull
, e você acaba passandovalue={undefined}
ouvalue={null}
ao seuinput
.Quando cheques ReactDOM para ver se um campo é controlado, ele verifica para ver se
value != null
(note que é!=
, não!==
), e uma vezundefined == null
em JavaScript, ele decide que é descontrolada.Portanto, quando
onFieldChange()
é chamado,this.state.name
é definido como um valor de sequência, sua entrada passa de descontrolada para controlada.Se você faz
this.state = {name: ''}
no seu construtor, porque'' != null
, sua entrada terá um valor o tempo todo e essa mensagem desaparecerá.fonte
this.props.<whatever>
, que foi o problema do meu lado. Obrigado Adam!render()
ou uma expressão na própria tag - qualquer coisa que seja avaliadaundefined
. Ainda bem que pude ajudar!name
".undefined
seja passado inicialmente. Pelo contrário, é o fato de quethis.state.name
não existe como uma variável de estado que torna a entrada descontrolada. Por exemplo, terthis.state = { name: undefined };
resultaria na entrada sendo controlada. Deve-se entender que o que importa é de onde vem o valor, não qual é o valor.this.state = { name: undefined }
ainda resultaria em uma entrada não controlada.<input value={this.state.name} />
desugars paraReact.createElement('input', {value: this.state.name})
. Como o acesso a uma propriedade inexistente de um objeto retornaundefined
, ele é avaliado exatamente para a mesma chamada de funçãoReact.createElement('input', {value: undefined})
-name
se não está definido ou explicitamente definido comoundefined
, portanto, o React se comporta da mesma maneira. Você pode ver esse comportamento neste JSFiddle.Outra abordagem pode ser definir o valor padrão dentro da sua entrada, assim:
fonte
Eu sei que outros já responderam isso. Mas um fator muito importante aqui pode ajudar outras pessoas com problemas semelhantes:
Você deve ter um
onChange
manipulador adicionado ao seu campo de entrada (por exemplo, campo de texto, caixa de seleção, rádio, etc.). Sempre lide com a atividade através doonChange
manipulador.Exemplo:
Quando você está trabalhando com a caixa de seleção, pode ser necessário lidar com seu
checked
estado!!
.Exemplo:
fonte
A solução simples para resolver esse problema é definir um valor vazio por padrão:
fonte
Uma desvantagem em potencial ao definir o valor do campo como "" (sequência vazia) no construtor é se o campo for um campo opcional e for deixado sem edição. A menos que você faça alguma massagem antes de postar seu formulário, o campo será mantido no armazenamento de dados como uma sequência vazia em vez de NULL.
Essa alternativa evitará cadeias vazias:
fonte
Ao usar
onChange={this.onFieldChange('name').bind(this)}
em sua entrada, você deve declarar a cadeia vazia do seu estado como um valor do campo de propriedade.maneira incorreta:
Maneira correta:
fonte
No meu caso, estava faltando algo realmente trivial.
<input value={state.myObject.inputValue} />
Meu estado era o seguinte quando recebi o aviso:
Ao alternar meu estado para referenciar a entrada do meu valor , meu problema foi resolvido:
fonte
Se os props do seu componente foram passados como um estado, coloque um valor padrão para suas tags de entrada
fonte
Defina um valor para a propriedade 'name' no estado inicial.
fonte
Uma atualização para isso. Para ganchos de reação, use
const [name, setName] = useState(" ")
fonte
" "
e não""
? Isso faz com que você perca qualquer texto de dica e, se você clicar e digitar, terá um espaço sorrateiro antes dos dados inseridos.Isso geralmente acontece apenas quando você não está controlando o valor do arquivado quando o aplicativo foi iniciado e após algum evento ou função disparar ou o estado ser alterado, agora você está tentando controlar o valor no campo de entrada.
Essa transição de não ter controle sobre a entrada e depois ter controle sobre ela é o que faz com que o problema ocorra em primeiro lugar.
A melhor maneira de evitar isso é declarando algum valor para a entrada no construtor do componente. Para que o elemento de entrada tenha valor desde o início do aplicativo.
fonte
Para definir dinamicamente propriedades de estado para entradas de formulário e mantê-las controladas, você pode fazer algo assim:
fonte
Simplesmente crie um fallback para '' se o this.state.name for nulo.
Isso também funciona com as variáveis useState.
fonte