11

Could you please tell me how to get input field value on button click in react , I am using react hooks .I want to get first name and lastname value on button click. I already pass name attribute in my function component.

Here is my code

import React, { Component, useState } from 'react';
import { render } from 'react-dom';

export default function InputField({name,label}) {
  const [state, setState] = useState('')
  return (
    <div>
     <label>{label}</label>
      <input type="text" 
      value={state} 
      name={name}
      onChange={(e) => setState(e.target.value)} />

      {state}
    </div>
  );

}
1
  • Hi user944513, have you had any luck integrating a solution to this problem? Aug 2, 2019 at 8:22

10 Answers 10

14

Use <form> tag with useRef hook

Wrap your <InputField> tags with an html <form> tag and put a react ref on the later. Like this:

import React, { Component, useRef } from 'react'
import { render } from 'react-dom'

import InputField from './inputfield'

import './style.css'

function App () {
  const nameForm = useRef(null)

  const handleClickEvent = () => {
     const form = nameForm.current
     alert(`${form['firstname'].value} ${form['lastname'].value}`)
  }

  return (
    <div>
      <form ref={nameForm}>
       <InputField label={'first name'} name={'firstname'}/>
       <InputField label={'last name'} name={'lastname'}/>
      </form>
      <button onClick={handleClickEvent}>gett value</button>
    </div>
  )
}

render(<App />, document.getElementById('root'))

Working example: https://stackblitz.com/edit/react-shtnxj

0
6

The Easiest Way For Me is useRef

With useRef it's pretty simple. Just add ref name and then submit.

const email = useRef(null);

function submitForm(e){
 e.preventDefault();
 
 console.log(email.current.value);
}

return (
 <div>
  <form onSubmit={submitForm}>
   <input type="text" ref={email} />
   <button>Submit</button>
  </form>
 </div>
)
3
  • But how can I use one ref for multiple fields? Jul 17, 2021 at 12:21
  • You can use ref in multiple fields too. for example: <input type="password" ref={password} />. or you can get the values from event.target.password.value without using useRef. I would suggest using external libraries like react-hooks-form, formik for faster production.
    – Mejan
    Jul 17, 2021 at 13:39
  • Actually, I am using react-hooks-form and the challenge is the nested form Jul 17, 2021 at 13:58
4

You could always lift up the state in parent component. codeSandbox link

Parent Component

import React from "react";
import ReactDOM from "react-dom";
import ChildComponent from "./Child";

const { useState } = React;

function App() {
  const [first_name, setFirstName] = useState("");
  const [last_name, setLastName] = useState("");
  const handleFirstNameChange = ({ target }) => {
    setFirstName(target.value);
  };
  const handleLastNameChange = ({ target }) => {
    setLastName(target.value);
  };
  const handleClick = () => {
    console.log(first_name);
    console.log(last_name);
  };
  return (
    <div className="App">
      <ChildComponent
        label="first name"
        onChange={handleFirstNameChange}
        value={first_name}
      />
      <ChildComponent
        label="last name"
        onChange={handleLastNameChange}
        value={last_name}
      />
      <button onClick={handleClick}>Click me</button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Child Component

import React from "react";

const ChildComponent = ({ label, onChange, value, name }) => {
  return (
    <div>
      <label>{label}</label>
      <input type="text" value={value} name={name} onChange={onChange} />
    </div>
  );
};

export default ChildComponent;

You could always combine onChange handler for first name and last name.

Hope that helps!!!

1

A good solution is to move the state from InputField component into index:

    const [F_name, setF_name] = useState('')
    const [L_name, setL_name] = useState('')

now you should pass state value and event handler to InputField to change the state when input is changed:

 <InputField label={'first name'} name={'firstname'} value={F_name} changed={(name) => setF_name(name)}/>

In Your InputField field: edit it to be like:

   <input type="text" 
      value={value} 
      name={name}
      onChange={(e) => changed(e.target.value)} />

See Working Demo Here

1

import React, { useRef } from 'react'
    const ViewDetail = () => {
      const textFirstName = useRef(null)   
      const onChange = e => {
        console.log(textFirstName.current.state.value) 
      } 
    
    return <Input maxLength={30} ref={textFirstName} placeholder="Nombre" onChange=onChange} />
  }

1
  • console.log(textFirstName.current.value) worked for me Jun 12, 2021 at 4:41
0

I can think of these approaches -

  • You can pull the state up to the parent component.

App.js

const [user, setUser] = useState('');

return (
 <Inputfield setValue={setUser} value={user} />
);

InputField.js

<input value={props.value}  onChange={(e) => setValue(e.target.value)} />

  • You can use ref to access indiviual element value.

  • If you have data distributed across multiple components you can also make use of Context API

Hope this helps!

Do let me know if you need more info on any of the option. Thanks!

0

You should do the react hooks work on your index and pass the value and the onChange function to your InputField component.

//index page
import React, { Component, useState } from 'react';
import { render } from 'react-dom';
import InputField from './inputfield';
import './style.css';

function App() {
  const [firstname, setFirstName] = useState('');
  const [lastname, setLastName] = useState('');
  const handleClickEvent = ()=>{
    setFirstName('Will');
    setLastName('smith');
  }

  return (
    <div>
      <InputField
        label={'first name'}
        name={'firstname'}
        value={firstname}
        onChange={setFirstName}
      />
      <InputField
        label={'last name'}
        name={'lastname'}
        value={lastname}
        onChange={setLastName}
      />
      <button 
        onClick={handleClickEvent}

      >Get value</button>
    </div>
  );

}

render(<App />, document.getElementById('root'));

// input field

import React, { Component, useState } from 'react';
import { render } from 'react-dom';

export default function InputField({name,label, value, onChange}) {
  return (
    <div>
     <label>{label}</label>
      <input type="text" 
      value={value} 
      name={name}
      onChange={(e) => onChange(e.target.value)} />

      {value}
    </div>
  );

}

0

While keeping the majority of your structure the same, I think the simplest and most React solution is to use forwardRef() which in a nut-shell let's us communicate between then parent-component and child-components.

See working sandbox.

App.js

import React, { useRef } from "react";
import InputField from "./InputField";
import ReactDOM from "react-dom";

function App() {
  const handleClickEvent = () => {
    if (firstName.current && lastName.current) {
      console.log(`firstName: ${firstName.current.value}`);
      console.log(`lastName: ${lastName.current.value}`);
    }
  };

  const firstName = useRef(null);
  const lastName = useRef(null);

  return (
    <div>
      <InputField ref={firstName} label={"first name"} name={"firstname"} />
      <InputField ref={lastName} label={"last name"} name={"lastname"} />
      <button onClick={handleClickEvent}>Get value</button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

InputField.js

import React, { useState } from "react";

const InputField = React.forwardRef((props, ref) => {
  const [state, setState] = useState("");
  return (
    <div>
      <label>{props.label}</label>
      <input
        ref={ref}
        type="text"
        value={state}
        name={props.name}
        onChange={e => setState(e.target.value)}
      />

      {state}
    </div>
  );
});

export default InputField;

Notice that with this structure, you are not required to pass in any state updating function as props to the InputField component. The value that you enter into each input will be strictly maintained by the individual component. It is independent from the Parent, and therefore makes it much more reusable.

The refs we created allow us to tap into specific elements of the InputField so we extract the desired values. In this case, we can get first-name and last-name through the handleClickEvent function.

0

you can achieve this doing the following:

import React, { Component, useState } from 'react';
import { render } from 'react-dom';

export default function InputField({name,label}) {
  const [state, setState] = useState('');
  const handleChange = e => {
    setState(e.target.value);
  };

  return (
    <div>
     <label>{label}</label>
      <input
        type="text" 
        value={state} 
        name={name}
        onChange={handleChange}
      />
      {state}
    </div>
  );
}

Hopes this helps.

-1

well one simple(but not necessarily recommended) way is to provide an id or a ref like this in index.js

<InputField label={'first name'} name={'firstname'} id={"ip1"}/>
<InputField label={'last name'} name={'lastname'} id={"ip2"}/>

and in your inputfield.js pass the id props to the input fields like this

<input type="text" 
      value={state} 
      name={name}
      onChange={(e) => setState(e.target.value)} 
      id= {id}/>

Now you can call them in the onClick of the button like this in index.js

const handleClickEvent = ()=>{
  alert(document.getElementById("ip1").value);
  }

The second, more preferable way is to set the state variable in index.js

function App() {
  const [stateIp1, setStateIp1] = useState('');
  const [stateIp2, setStateIp2] = useState('');
  const handleClickEvent = ()=>{
  alert(stateIp1);
  }
  return (
    <div>
      <InputField label={'first name'} state={stateIp1} setState={setStateIp1} name={'firstname'} id={"ip1"}/>
        <InputField label={'last name'}state={stateIp2} setState={setStateIp2} name={'lastname'} id={"ip2"}/>
        <button 
          onClick={handleClickEvent}

        >Get value</button>
    </div>
  );

}

Now your inputfield.js becomes

export default function InputField({name,label,id,setState,state}) {

  return (
    <div>
     <label>{label}</label>
      <input type="text" 
      value={state} 
      name={name}
      onChange={(e) => setState(e.target.value)} id= {id}/>
    </div>
  );
2
  • 1
    you should avoid using document in react. See: stackoverflow.com/questions/38093760/… Aug 1, 2019 at 6:28
  • @KareemDabbeet Yes, I know which is why I said "simple(but not necessarily recommended) way" and also I've edited the answer with the second option....I accidentaly posted only the first part of my answer Aug 1, 2019 at 6:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.