How to get the value of an input field using ReactJS?

JavascriptReactjs

Javascript Problem Overview


I have the following React component:

export default class MyComponent extends React.Component {

    onSubmit(e) {
        e.preventDefault();
        var title = this.title;
        console.log(title);
    }

    render(){
        return (
            ...
            <form className="form-horizontal">
                ...
                <input type="text" className="form-control" ref={(c) => this.title = c} name="title" />
                ...
            </form>
            ...
            <button type="button" onClick={this.onSubmit} className="btn">Save</button>
            ...
        );
    }

};

The console is giving me undefined - any ideas what's wrong with this code?

Javascript Solutions


Solution 1 - Javascript

There are three answers here, depending on the version of React you're (forced to) work(ing) with, and whether you want to use hooks.

First things first:

It's important to understand how React works, so you can do things properly (protip: it's super worth running through the React tutorial on the React website. It's well written, and covers all the basics in a way that actually explains how to do things). "Properly" here means that you're not writing a web page, you're writing the user interface for an application that happens to be rendered in a browser; all the actual user interface work happens in React, not in "what you're used to from writing a web page" (this is why React apps really are "apps", not "web pages").

React applications are rendered based off of two things:

  1. the component's properties as declared by whichever parent creates an instance of that component, which the parent can modify throughout its lifecycle, and
  2. the component's own internal state, which it can modify itself throughout its own lifecycle.

What you're expressly not doing when you use React is generating HTML elements and then using those: when you tell React to use an <input>, for instance, you are not creating an HTML input element, you are telling React to create a React input object that happens to render as an HTML input element when your compile your React app for the web, and whose event handling listens to, but is not controlled by, the HTML element's input events.

When using React, what you're doing is generating application UI elements that present the user with (often manipulable) data, for with user interaction changing the state of your application in some way that you define - actions performed by the user may update a component's props or state, which React uses as a signal to generate a new UI representation of your component, which may cause an update of part of your application interface to reflect the new state. In this model, the app's internal state is always the final authority, not "whatever UI library or technology is used to render the app". So the DOM is effectively almost an afterthought in this programming model: it just happens to be a super convenient UI framework that the entire planet is virtually guaranteed to have access to (and it's not the only one React knows how to work with).

So let's look how a user interacting with an input element works in React. First, we need to get to having a UI element for the user to interact with:

  1. You wrote a component to manage (i.e. both store and present) some string data for your users.
  2. Your component's rendering code is used by React to generate a virtual DOM that contains an <input> component (not a DOM element) with a React onChange handler (not a DOM event listener).
  3. The React library then translates that virtual DOM into updates to the UI for to the user to see/interact with. Since it's running in the browser, it builds an HTML input element.

Then, your user tries to actually interact with that input element:

  1. Your user clicks on the input element and starts typing.
  2. Nothing happens to your input element yet, the input events get intercepted by React and killed off immediately.
  3. React forwards those event to the function you've set up for event handling.
  4. That function may do something, which in this case is almost certainly scheduling a state update for the string data that this component is supposed to manage.
  5. If a state update got scheduled, React will run that state update (asynchronously!) and will trigger a render pass after the update, but only if the state update changed the state.
  6. If it did, a new virtual DOM is generated, which gets compared to the previous virtual DOM, the difference is turned into a set of diff operations, and those get applied to the real DOM. In this case, assuming we're using React code similar to <input value={textFromState}.../>, that update will be to change the value that the input element presents to the user.
  7. After the DOM update gets applied, the user now sees what they typed in the input element.

So this is completely different from the regular browser model: instead of the user updating the UI data by typing into a text box first and our code reading "the current value of that text box" to figure out what the state is second, React already knows what the state is, and uses events to update the state first, which leads to a UI update second.

OF all of that happens near instantly, so to your user it looks like they typed text into an input element in the same way they're used to from "just using an input element on a web page", but under the hood things couldn't be more different while still leading to the same result.

So, with that covered, let's look at how to get values from elements in React:

Component classes and ES6 (React 16+ and 15.5 transitional)

As of React 16 (and soft-starting with 15.5) the createClass call is no longer supported, and class syntax needs to be used. This changes two things: the obvious class syntax, but also the thiscontext binding that createClass can do "for free", so to ensure things still work make sure you're using "fat arrow" notation for this context preserving anonymous functions in onWhatever handlers, such as the onChange we use in the code here:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      inputValue: ''
    };
  }

  render() {
    return (
      // ...
      <input value={this.state.inputValue} onChange={evt => this.updateInputValue(evt)}/>
      // ...
    );
  },

  updateInputValue(evt) {
    const val = evt.target.value;
    // ...
    this.setState({
      inputValue: updatedInputValue
    });
  }
});

You may also have seen people use bind in their constructor for all their event handling functions, like this:

constructor(props) {
  super(props);
  this.handler = this.handler.bind(this);
  ...
}

render() {
  return (
    ...
    <element onclick={this.handler}/>
    ...
  );
}

Don't do that.

Almost any time you're using bind, the proverbial "you're doing it wrong" applies. Your class already defines the object prototype, and so already defines the instance context. Don't put bind of top of that; use normal event forwarding instead of duplicating all your function calls in the constructor, because that duplication increases your bug surface, and makes it much harder to trace errors because the problem might be in your constructor instead of where you call your code.

Function components with hooks (React 16.8+)

As of React 16.8 the function component (i.e. literally just a function that takes some props as argument can be used as if it's an instance of a component class, without ever writing a class) can also be given state, through the use of hooks.

If you don't need full class code, and a single instance function will do, then you can now use the useState hook to get yourself a single state variable, and its update function, which works roughly the same as the above examples, except without the "universal" setState function call and using one dedicated state setter for each value you're working with:

import { useState } from 'react';

function myFunctionalComponentFunction() {
  const [input, setInput] = useState(''); // '' is the initial state value
  return (
    <div>
    <label>Please specify:</label>
    <input value={input} onInput={e => setInput(e.target.value)}/>
    </div>
  );
}

Previously the unofficial distinction between classes and function components was "function components don't have state", so we can't hide behind that one anymore: the difference between function components and classes components can be found spread over several pages in the very well-written react documentation (no shortcut one liner explanation to conveniently misinterpret for you!) which you should read so that you know what you're doing and can thus know whether you picked the best (whatever that means for you) solution to program yourself out of a problem you're having.

React 15 and below, using legacy ES5 and createClass

To do things properly, your component has a state value, which is shown via an input field, and we can update it by making that UI element send change events back into the component:

var Component = React.createClass({
  getInitialState: function() {
    return {
      inputValue: ''
    };
  },

  render: function() {
    return (
      //...
      <input value={this.state.inputValue} onChange={this.updateInputValue}/>
      //...
    );
  },

  updateInputValue: function(evt) {
    this.setState({
      inputValue: evt.target.value
    });
  }
});

So we tell React to use the updateInputValue function to handle the user interaction, use setState to schedule the state update, and the fact that render taps into this.state.inputValue means that when it rerenders after updating the state, the user will see the update text based on what they typed.

addendum based on comments

Given that UI inputs represent state values (consider what happens if a user closes their tab midway, and the tab is restored. Should all those values they filled in be restored? If so, that's state). That might make you feel like a large form needs tens or even a hundred input forms, but React is about modeling your UI in a maintainable way: you do not have 100 independent input fields, you have groups of related inputs, so you capture each group in a component and then build up your "master" form as a collection of groups.

MyForm:
  render:
    <PersonalData/>
    <AppPreferences/>
    <ThirdParty/>
     ...

This is also much easier to maintain than a giant single form component. Split up groups into Components with state maintenance, where each component is only responsible for tracking a few input fields at a time.

You may also feel like it's "a hassle" to write out all that code, but that's a false saving: developers-who-are-not-you, including future you, actually benefit greatly from seeing all those inputs hooked up explicitly, because it makes code paths much easier to trace. However, you can always optimize. For instance, you can write a state linker

MyComponent = React.createClass({
  getInitialState() {
    return {
      firstName: this.props.firstName || "",
      lastName: this.props.lastName || "" 
      ...: ...
      ...
    }
  },
  componentWillMount() {
    Object.keys(this.state).forEach(n => {
      let fn = n + 'Changed';
      this[fn] = evt => {
        let update = {};
        update[n] = evt.target.value;
        this.setState(update);
      });
    });
  },
  render: function() {
    return Object.keys(this.state).map(n => {
      <input
        key={n} 
        type="text"
        value={this.state[n]}
        onChange={this[n + 'Changed']}/>
    });
  }
});

Solution 2 - Javascript

Managed to get the input field value by doing something like this:

import React, { Component } from 'react';

class App extends Component {

constructor(props){
super(props);

this.state = {
  username : ''
}

this.updateInput = this.updateInput.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}


updateInput(event){
this.setState({username : event.target.value})
}


handleSubmit(){
console.log('Your input value is: ' + this.state.username)
//Send state to the server code
}



render(){
return (
    <div>
    <input type="text" onChange={this.updateInput}></input>
    <input type="submit" onClick={this.handleSubmit} ></input>
    </div>
  );
}
} 

//output
//Your input value is: x

Solution 3 - Javascript

You should use constructor under the class MyComponent extends React.Component

constructor(props){
    super(props);
    this.onSubmit = this.onSubmit.bind(this);
  }

Then you will get the result of title

Solution 4 - Javascript

In react 16, I use

<Input id="number" 
       type="time" 
       onChange={(evt) => { console.log(evt.target.value); }} />

Solution 5 - Javascript

Give the <input> a unique id

<input id='title' ...>

and then use the standard Web API to reference it in the DOM

const title = document.getElementById('title').value

No need to continually update the React state with every keypress. Simply get the value when it's required.

Solution 6 - Javascript

export default class App extends React.Component{
     state={
         value:'',
         show:''
      }

handleChange=(e)=>{
  this.setState({value:e.target.value})
}

submit=()=>{
   this.setState({show:this.state.value})
}

render(){
    return(
        <>
          <form onSubmit={this.submit}>
             <input type="text" value={this.state.value} onChange={this.handleChange} />
             <input type="submit" />
          </form>
          <h2>{this.state.show}</h2>
        </>
        )
    }
}

Solution 7 - Javascript

In Function Component :-

export default function App(){

const [state, setState] = useState({
        value:'',
        show:''
    });

const handleChange = (e) => {
    setState({value: e.target.value})
}

const submit = () => {
    setState({show: state.value})
}

return(
        <>
            <form onSubmit={()=>submit()}>
                <input type="text" value={state.value} onChange={(e)=>handleChange(e)} />
                <input type="submit" />
            </form>
            <h2>{state.show}</h2>
        </>
)}

Solution 8 - Javascript

I succeeded in doing this by binding this to the function updateInputValue(evt) with

this.updateInputValue = this.updateInputValue.bind(this);

However input value={this.state.inputValue} ... turned out to be no good idea.

Here's the full code in babel ES6 :

class InputField extends React.Component{

    
  constructor(props){
   super(props);
   //this.state={inputfield: "no value"};   
   this.handleClick = this.handleClick.bind(this);
   this.updateInputValue = this.updateInputValue.bind(this);
  }
  
  handleClick(){
   console.log("trying to add picture url");
   console.log("value of input field : "+this.state.inputfield);
   
  }
 
  updateInputValue(evt){
    //console.log("input field updated with "+evt.target.value);
    this.state={inputfield: evt.target.value};   
    
  }

  render(){
    var r; 
    r=<div><input type="text" id="addpixinputfield" 
            onChange={this.updateInputValue} />
      <input type="button" value="add" id="addpix" onClick={this.handleClick}/>
      </div>;    
    return r;
   }
}

Solution 9 - Javascript

In Function Component

useState

Returns a stateful value, and a function to update it. During the initial render, the returned state (state) is the same as the value passed as the first argument (initialState). The setState function is used to update the state. It accepts a new state value and enqueues a re-render of the component.
src ---> https://reactjs.org/docs/hooks-reference.html#usestate

useRef

useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component.
src ---> https://reactjs.org/docs/hooks-reference.html#useref

import { useRef, useState } from "react";

export default function App() {
  const [val, setVal] = useState('');
  const inputRef = useRef();

  const submitHandler = (e) => {
    e.preventDefault();

    setVal(inputRef.current.value);
  }

  return (
    <div className="App">
      <form onSubmit={submitHandler}>
        <input ref={inputRef} />
        <button type="submit">Submit</button>
      </form>

      <p>Submit Value: <b>{val}</b></p>
    </div>
  );
}

Solution 10 - Javascript

your error is because of you use class and when use class we need to bind the functions with This in order to work well. anyway there are a lot of tutorial why we should "this" and what is "this" do in javascript.

if you correct your submit button it should be work:

<button type="button" onClick={this.onSubmit.bind(this)} className="btn">Save</button>

and also if you want to show value of that input in console you should use var title = this.title.value;

Solution 11 - Javascript

// On the state
constructor() {
  this.state = {
   email: ''
 }
}

// Input view ( always check if property is available in state {this.state.email ? this.state.email : ''}

<Input 
  value={this.state.email ? this.state.email : ''} 
  onChange={event => this.setState({ email: event.target.value)}
  type="text" 
  name="emailAddress" 
  placeholder="[email protected]" />

Solution 12 - Javascript

This simplest way is to use arrow function

Your code with arrow functions

export default class MyComponent extends React.Component {

onSubmit = (e) => {
    e.preventDefault();
    var title = this.title;
    console.log(title);
}

render(){
    return (
        ...
        <form className="form-horizontal">
            ...
            <input type="text" className="form-control" ref={(c) => this.title = c} name="title" />
            ...
        </form>
        ...
        <button type="button" onClick={this.onSubmit} className="btn">Save</button>
        ...
    );
}

};

Solution 13 - Javascript

  • React Version: 17.0.1

    a) Using Functional Components

    b) Manage state using hook: useState().

Write and Run code as above:

import React, {useState} from 'react';

const InputElement = () => {
  const [inputText, setInputText] = useState('');

  return (
   <div> 
        <input
              onChange={(e) => {
                  setInputText(e.target.value);
                   }                   
             }
             placeholder='Enter Text'
       />
       {inputText}
   </div>
 );
}

The solving scheme algorithm is similar to a two-way data binding:

> input <=> DATA_MODEL <=> Label_Text

Solution 14 - Javascript

You can get an input value without adding 'onChange' function.

Just add to the input element a 'ref attr:

And then use this.refs to get the input value when you need it.

Solution 15 - Javascript

Change your ref into: ref='title' and delete name='title' Then delete var title = this.title and write:

console.log(this.refs.title.value)

Also you should add .bind(this) to this.onSubmit

(It worked in my case which was quite similar, but instead of onClick I had onSubmit={...} and it was put in form ( <form onSubmit={...} ></form>))

Solution 16 - Javascript

if you use class component then only 3 steps- first you need to declare state for your input filed for example this.state = {name:''}. Secondly, you need to write a function for setting the state when it changes in bellow example it is setName() and finally you have to write the input jsx for example < input value={this.name} onChange = {this.setName}/>

import React, { Component } from 'react'

export class InputComponents extends Component {
    constructor(props) {
        super(props)
    
        this.state = {
             name:'',
             agree:false
        }
        this.setName = this.setName.bind(this);
        this.setAgree=this.setAgree.bind(this);
    }
    
    setName(e){
        e.preventDefault();
        console.log(e.target.value);
        this.setState({
            name:e.target.value
        })
    }
    setAgree(){
        this.setState({
            agree: !this.state.agree
        }, function (){
            console.log(this.state.agree);
        })
    }
    render() {
        return (
            <div>
                <input type="checkbox" checked={this.state.agree} onChange={this.setAgree}></input>
                < input value={this.state.name} onChange = {this.setName}/>
            </div>
        )
    }
}

export default InputComponents

Solution 17 - Javascript

export default class MyComponent extends React.Component {

onSubmit(e) {
    e.preventDefault();
    var title = this.title.value; //added .value
    console.log(title);
}

render(){
    return (
        ...
        <form className="form-horizontal">
            ...
            <input type="text" className="form-control" ref={input => this.title = input} name="title" />
            ...
        </form>
        ...
        <button type="button" onClick={this.onSubmit} className="btn">Save</button>
        ...
    );
}

};

Solution 18 - Javascript

using uncontrolled fields:

export default class MyComponent extends React.Component {

    onSubmit(e) {
        e.preventDefault();
        console.log(e.target.neededField.value);
    }

    render(){
        return (
            ...
            <form onSubmit={this.onSubmit} className="form-horizontal">
                ...
                <input type="text" name="neededField" className="form-control" ref={(c) => this.title = c}/>
                ...
            </form>
            ...
            <button type="button" className="btn">Save</button>
            ...
        );
    }

};

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJoeTideeView Question on Stackoverflow
Solution 1 - JavascriptMike 'Pomax' KamermansView Answer on Stackoverflow
Solution 2 - JavascriptHugo WesleyView Answer on Stackoverflow
Solution 3 - JavascriptMd. Maidul IslamView Answer on Stackoverflow
Solution 4 - JavascriptPyae SoneView Answer on Stackoverflow
Solution 5 - JavascriptBrent WashburneView Answer on Stackoverflow
Solution 6 - JavascriptrahulfaujdarView Answer on Stackoverflow
Solution 7 - JavascriptrahulfaujdarView Answer on Stackoverflow
Solution 8 - JavascriptMatthias LisztView Answer on Stackoverflow
Solution 9 - JavascriptMd. Jahid HossainView Answer on Stackoverflow
Solution 10 - JavascriptSoroush BkView Answer on Stackoverflow
Solution 11 - JavascriptKidali KevinView Answer on Stackoverflow
Solution 12 - JavascriptBilly SomersView Answer on Stackoverflow
Solution 13 - JavascriptRigers LekaView Answer on Stackoverflow
Solution 14 - JavascriptzordonView Answer on Stackoverflow
Solution 15 - JavascriptKatarzyna WroĊ„skaView Answer on Stackoverflow
Solution 16 - JavascriptRafiqView Answer on Stackoverflow
Solution 17 - JavascriptPranav AgarwalView Answer on Stackoverflow
Solution 18 - JavascriptGeorgView Answer on Stackoverflow