165

I'm trying my first bit of React.js and am stumped early on... I have the code below, which renders a search form into <div id="search"></div>. But typing in the search box does nothing.

Presumably something is going missing passing the props and state up and down, and this seems like a common problem. But I'm stumped - I can't see what's missing.

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')
);

(Eventually I will have other types of SearchFacet* but I'm just trying to get this one working.)

Phil Gyford
  • 13,432
  • 14
  • 81
  • 143
  • Try logging `this` when you input the text field. It could be that `this` is not the `Searcher` component anymore. – Matias Faure Nov 30 '15 at 19:31
  • Thanks FaureHu - logging `this` at which point in the code? Trying to log from `Searcher.handleUserInput()` or `SearchFacet.handleChange()` doesn't do anything. – Phil Gyford Nov 30 '15 at 19:34
  • you can see my answer for similar questions. You can find detailed explanation: http://stackoverflow.com/questions/34713718/input-field-doesnt-receive-keyboard-events-when-rendering-with-value-property/36871399?noredirect=1#comment61310144_36871399 – prudhvi seeramreddi Apr 26 '16 at 17:26

12 Answers12

267

Using value={whatever} will make it so you cannot type in the input field. You should use defaultValue="Hello!".

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

Also, the onchange should be onChange as @davnicwil points out.

michaelmerg
  • 348
  • 2
  • 5
Ivan
  • 10,052
  • 12
  • 47
  • 78
  • 4
    In my requirement i wanted to input field with typing enable as well as it needs to be set to default value came from a state variable. defaultValue attribute was fine but there is a problem in updating default value according to state changes, is there some way to force default value to change? – semira Jul 19 '16 at 05:51
  • 1
    You should post that issue as another question on Stackoverflow. – Ivan Jul 19 '16 at 14:49
  • 1
    @GeoffreyHale I'm not quite sure what you mean by how it is misleading. See this example that doesn't use state: https://codepen.io/anon/pen/BQJZwr?editors=0010. Or this one that does: https://codepen.io/anon/pen/JbMJMX?editors=0010 – Ivan Dec 01 '16 at 18:26
  • 5
    @Ivan You are right, both are immutable: `value={whatever}` and `value={this.state.myvalue}`. I should have made *this clarification* instead: using `onChange={this.handleChange}` and anything like `handleChange: function(e) { var newState = {}; newState[e.target.name] = e.target.value; this.setState(newState); },` makes fields mutable again. – Geoffrey Hale Dec 01 '16 at 22:39
  • 1
    @ivan, maybe update your answer to say `defaultValue={whatever}` can be used. It's not the fact that it's not straight text, it's the fact that using `value` makes it immutable but you can assign anything to `defaultValue` and still be able to edit it after the fact – StudioTime Mar 01 '19 at 12:00
  • When using Formik validation, I think it's necessary to use ```value```, no? Could you have a look here? onChange doesn't work for me https://stackoverflow.com/questions/61689720/onchange-on-textinput-not-working-inside-formik –  May 08 '20 at 23:36
99

You haven't properly cased your onchange prop in the input. It needs to be onChange in JSX.

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

The topic of passing a value prop to an <input>, and then somehow changing the value passed in response to user interaction using an onChange handler is pretty well-considered in the docs.

They refer to such inputs as Controlled Components, and refer to inputs that instead let the DOM natively handle the input's value and subsequent changes from the user as Uncontrolled Components.

Whenever you set the value prop of an input to some variable, you have a Controlled Component. This means you must change the value of the variable by some programmatic means or else the input will always hold that value and will never change, even when you type -- the native behaviour of the input, to update its value on typing, is overridden by React here.

So, you're correctly taking that variable from state, and have a handler to update the state all set up fine. The problem was because you have onchange and not the correct onChange the handler was never being called and so the value was never being updated when you type into the input. When you do use onChange the handler is called, the value is updated when you type, and you see your changes.

davnicwil
  • 28,487
  • 16
  • 107
  • 123
24

For me the following simple change worked perfectly

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

change... value={myPropVal} to... defaultValue={myPropVal}

<input type="text" 
        defaultValue={props.letter} 
        onChange={event => setTxtLetter(event.target.value)} /> {/* Works!! */}
Michael Nelles
  • 5,426
  • 8
  • 41
  • 57
  • I think onChange doesn't work properly when used within Formik. I was trying this too but it didn't work for me. Could you please have a look here? https://stackoverflow.com/questions/61689720/onchange-on-textinput-not-working-inside-formik –  May 08 '20 at 23:37
12

This might be caused by the onChange function is not updating the proper value which is mentioned in the input.

Example:

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

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

in the onChange function update the mentioned value field.

Pardeep Sharma
  • 301
  • 4
  • 14
sunaina kotekar
  • 933
  • 7
  • 7
6

Instead of value use defaultValue

We use value when the fields are empty, but if we have to type or update the value from the value already in the input box. We must use defaultValue

Hana Jiffry
  • 61
  • 1
  • 1
4

I also have same problem and in my case I injected reducer properly but still I couldn't type in field. It turns out if you are using immutable you have to use 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 */

Notice that your state should be like state->form otherwise you have to explicitly config the library also the name for state should be form. see this issue

artronics
  • 1,399
  • 2
  • 19
  • 28
1

In a class component context...

If the changeHandler method is a normal function:

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

it can be used such as this...onChange={(e)=>this.handleChange(e)}

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

If the changeHandler method is an arrow function:

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

it can be used like this... onChange={this.handle}

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

And this solved my "Can't type in React input text field" problem.

Aditya Patnaik
  • 1,490
  • 17
  • 27
0

Give the onChange to the searchTool.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Arun Kumar
  • 11
  • 1
0

Once I ran into a similar error. Let me describe it.

Edit.js

   // components returns edit form 
   
   function EditVideo({id}) {
   .....
   
   // onChange event listener 
    const handleChange = (e) => {
       setTextData({
           ...textData,
           [e.target.name]: e.target.value.trim()
        });
     }
  
   ....
   ...
   }
)

ImportEdit.js

   import Edit from './Edit';
   
    function ImportEdit() {
    ......
     ...
    return (
        <div>
            <EditVideo id={id}/>
        </div>
       )
    }

    export default ImportEdit

The Problem was: I was unable to use spacebar (i.e. if i press spacekey, i didn't see space input)

The Bug: .trim()

.trim() method was trimming all the white space i typed

Note: Edit.js worked fine when used sepeartely without import

Harshit Gangwar
  • 553
  • 7
  • 14
0

In my case i use Material ui and also needed name="data" (same as state)

 <TextField name="fecha" id="fecha" label="fecha"  value={this.state.fecha} onChange={this.handleInputChange} />

the name value is needed for react works

0

I got a similar problem, i fixed it by adding a value and a name params to each input i used.

Here an example:

const onValueChange = (e) => {
    setProduct({ ...product, [e.target.name]: e.target.value })
}
//...
<input
      type="number"
      id="exampleFormControlInput4"
      label="Price :"
      placeholder="Enter price"
      text="Must be a number"
      aria-describedby="exampleFormControlInputHelpInline"
      onChange={(e) => onValueChange(e)}
      value={price}
      name="price"
/>
Ava
  • 512
  • 2
  • 26
-1

Check your input field names. I corrected my input field names and issue solved for me.

Jay
  • 1
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/33634506) – Tushar Jan 19 '23 at 13:23