10

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

}
Edgar
  • 6,022
  • 8
  • 33
  • 66
user944513
  • 12,247
  • 49
  • 168
  • 318

10 Answers10

12

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

UtkarshPramodGupta
  • 7,486
  • 7
  • 30
  • 54
5

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>
)
Mejan
  • 918
  • 13
  • 18
  • But how can I use one ref for multiple fields? – Hidayt Rahman Jul 17 '21 at 12:21
  • You can use ref in multiple fields too. for example: ``. 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 '21 at 13:39
  • Actually, I am using `react-hooks-form` and the challenge is the nested form – Hidayt Rahman Jul 17 '21 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!!!

tarzen chugh
  • 10,561
  • 4
  • 20
  • 30
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

Kareem Dabbeet
  • 3,838
  • 3
  • 16
  • 34
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} />
  }
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!

Yash Joshi
  • 2,586
  • 1
  • 9
  • 18
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>
  );

}

Akram Badah
  • 417
  • 3
  • 12
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.

ross
  • 2,684
  • 2
  • 13
  • 22
Chris Ngo
  • 15,460
  • 3
  • 23
  • 46
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.

Alberto Perez
  • 2,561
  • 1
  • 14
  • 21
-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>
  );
akshay kishore
  • 1,017
  • 8
  • 16
  • 1
    you should avoid using `document` in react. See: https://stackoverflow.com/questions/38093760/how-to-access-a-dom-element-in-react-what-is-the-equilvalent-of-document-getele/38093981#38093981 – Kareem Dabbeet Aug 01 '19 at 06: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 – akshay kishore Aug 01 '19 at 06:34