Não é possível digitar no campo de texto de entrada React

111

Estou tentando minha primeira parte do React.js e estou perplexo no início ... Tenho o código abaixo, que renderiza um formulário de pesquisa em <div id="search"></div>. Mas digitar na caixa de pesquisa não adianta nada.

Presumivelmente, algo está faltando, passando os adereços e o estado para cima e para baixo, e isso parece um problema comum. Mas estou perplexo - não consigo ver o que está faltando.

var SearchFacet = React.createClass({
  handleChange: function() {
    this.props.onUserInput(
      this.refs.searchStringInput.value
    )
  },
  render: function() {
    return (
      <div>
        Search for:
        <input
          type="text"
          value={this.props.searchString}
          ref="searchStringInput"
          onchange={this.handleChange} />
      </div>
    );
  }
});

var SearchTool = React.createClass({
  render: function() {
    return (
      <form>
        <SearchFacet 
          searchString={this.props.searchString}
          onUserInput={this.props.onUserInput}
         />
        <button>Search</button>
      </form>
    );
  }
});

var Searcher = React.createClass({
  getInitialState: function() {
    return {
      searchString: ''
    }
  },

  handleUserInput: function(searchString) {
    this.setState({
      searchString: searchString
    })
  },

  render: function() {
    return (
      <div>
        <SearchTool 
          searchString={this.state.searchString}
          onUserInput={this.handleUserInput}
        />
      </div>
    );
  }
});

ReactDOM.render(
  <Searcher />,
  document.getElementById('searcher')
);

(Eventualmente terei outros tipos de, SearchFacet*mas estou apenas tentando fazer este funcionar.)

Phil Gyford
fonte
Tente registrar thisao inserir o campo de texto. Pode ser que thisnão seja mais o Searchercomponente.
FaureHu
Obrigado FaureHu - logando thisem que ponto do código? Tentando logar Searcher.handleUserInput()ou SearchFacet.handleChange()não faz nada.
Phil Gyford
você pode ver minha resposta para perguntas semelhantes. Você pode encontrar a explicação detalhada: stackoverflow.com/questions/34713718/…
prudhvi seeramreddi

Respostas:

80

Você não encaixou corretamente seu onchangesuporte no input. Precisa estar onChangeem JSX.

<input
  type="text"
  value={this.props.searchString}
  ref="searchStringInput"
  onchange={this.handleChange} <--[should be onChange]
/>  

O tópico de passar uma valueprop para um <input>e, em seguida, alterar de alguma forma o valor passado em resposta à interação do usuário usando um onChangemanipulador é muito bem considerado nos documentos .

Eles se referem a essas entradas como componentes controlados e se referem a entradas que, em vez disso, permitem que o DOM manipule nativamente o valor da entrada e as alterações subsequentes do usuário como componentes não controlados .

Sempre que você define o valueprop de um inputpara alguma variável, você tem um componente controlado . Isso significa que você deve alterar o valor da variável por algum meio programático ou a entrada sempre manterá esse valor e nunca mudará, mesmo quando você digitar - o comportamento nativo da entrada, para atualizar seu valor na digitação, é sobrescrito por React aqui.

Então, você está retirando corretamente essa variável do estado e tem um manipulador para atualizar o estado, tudo configurado corretamente. O problema era porque você tinha onchangee não o correto, onChangeo manipulador nunca estava sendo chamado e, portanto, o valuenunca estava sendo atualizado quando você digita na entrada. Quando você usa, onChangeo manipulador é chamado, o value é atualizado quando você digita e você vê suas alterações.

Davnicwil
fonte
201

Usar value={whatever}fará com que você não possa digitar no campo de entrada. Você deve usar defaultValue="Hello!".

Consulte https://facebook.github.io/react/docs/uncontrolled-components.html#default-values

Além disso, onchangedeve ser onChangecomo @davnicwil aponta.

Ivan
fonte
2
No meu requisito, eu queria inserir um campo com habilitação de digitação, assim como ele precisa ser definido para o valor padrão vindo de uma variável de estado. O atributo defaultValue estava bem, mas há um problema na atualização do valor padrão de acordo com as mudanças de estado. Existe alguma maneira de forçar a mudança do valor padrão?
semira
1
Você deve postar esse problema como outra pergunta no Stackoverflow.
Ivan
1
@GeoffreyHale Não tenho certeza do que você quer dizer com enganoso. Veja este exemplo que não usa state: codepen.io/anon/pen/BQJZwr?editors=0010 . Ou este que faz: codepen.io/anon/pen/JbMJMX?editors=0010
Ivan
4
@Ivan Você está certo, ambos são imutáveis: value={whatever}e value={this.state.myvalue}. Eu deveria ter feito este esclarecimento : o uso de onChange={this.handleChange}e qualquer coisa semelhante handleChange: function(e) { var newState = {}; newState[e.target.name] = e.target.value; this.setState(newState); },torna os campos mutáveis ​​novamente.
Geoffrey Hale
1
@Ivan Este apenas me ajudou, muito obrigado, defaultValuesalve o meu dia.
Code Cooker
11

Isso pode ser causado pela função onChange não estar atualizando o valor apropriado que é mencionado na entrada.

Exemplo:

<input type="text" value={this.state.textValue} onChange = {this.changeText}></input>

 changeText(event){
        this.setState(
            {textValue : event.target.value}
        );
    }

na função onChange atualize o campo de valor mencionado.

sunaina kotekar
fonte
Obrigado, muito útil. Apenas sua resposta explica completamente como resolver o problema.
M3RS
onde definir essa função changeText?
Jitendra Pancholi
Se for um componente sem estado, dentro da função, e se for um componente de classe, dentro do construtor.
Gal Grünfeld
você não precisa escrever this.state dentro de setState. Se você só escrever textValue: event.target.value dentro de setState, também funcionará perfeitamente
Pardeep Sharma
4

Também estou com o mesmo problema e no meu caso injetei redutor corretamente mas ainda não consegui digitar no campo. Acontece que se você está usando, immutablevocê tem que usar redux-form/immutable.

import {reducer as formReducer} from 'redux-form/immutable';
const reducer = combineReducers{

    form: formReducer
}
import {Field, reduxForm} from 'redux-form/immutable';
/* your component */

Observe que seu estado deve ser state->formigual, caso contrário, você terá que configurar explicitamente a biblioteca e o nome do estado deve ser form. veja este problema

Seyed Jalal Hosseini
fonte
4

Para mim, a seguinte mudança simples funcionou perfeitamente

<input type="text" 
        value={props.letter} 
        onChange={event => setTxtLetter(event.target.value)} /> {/* does not work */}

alterar ... valor = {myPropVal} para ... defaultValue = {myPropVal}

<input type="text" 
        defaultValue={props.letter} 
        onChange={event => setTxtLetter(event.target.value)} /> {/* Works!! */}
Nelles
fonte
Isso consertou para mim. Obrigado!
mikeym
Acho que o onChange não funciona corretamente quando usado no Formik. Eu estava tentando fazer isso também, mas não funcionou para mim. Você poderia dar uma olhada aqui? stackoverflow.com/questions/61689720/…
a125
0

Em um contexto de componente de classe ...

Se o método changeHandler for uma função normal:

handleChange(e){
    this.setState({[e.target.name]:[e.target.value]});
}

pode ser usado assim ...onChange={(e)=>this.handleChange(e)}

<input type="text" name="any" value={this.state.any} onChange={(e)=>this.handleChange(e)}></input>

Se o método changeHandler for uma função de seta:

handle = (e) =>{
        this.setState({[e.target.name]:[e.target.value]});
    }

pode ser usado assim ... onChange={this.handle}

 <input type="text" name="any2" value={this.state.any2} onChange={this.handle} ></input>

E isso resolveu meu problema "Não é possível digitar no campo de texto de entrada React".

Aditya Patnaik
fonte