myusuf
myusuf

Reputation: 12260

Get form data in React

I have a simple form in my render function, like so:

render : function() {
      return (
        <form>
          <input type="text" name="email" placeholder="Email" />
          <input type="password" name="password" placeholder="Password" />
          <button type="button" onClick={this.handleLogin}>Login</button>
        </form>
      );
    },
handleLogin: function() {
   // How can I access email and password here?
}

What should I write in my handleLogin: function() { ... } to access Email and Password fields?

Upvotes: 376

Views: 754772

Answers (30)

Wickramaranga
Wickramaranga

Reputation: 1181

For the people living in the future,

Looks like it took some time for React to provide a proper answer to this with React 19 <form> component. Be careful that this is a Canary release and not production ready yet.

To quote the example in the docs verbatim:

export default function Search() {
  function search(formData) {
    const query = formData.get("query");
    alert(`You searched for '${query}'`);
  }
  return (
    <form action={search}>
      <input name="query" />
      <button type="submit">Search</button>
    </form>
  );
}

Now it's pretty straightforward to access form fields. But be aware of a few things:

  • Previously, form action was a string such as "/submit" which was the path of the page to GET, or POST if form method="POST".
  • If you want to do multiple things with different buttons, you can also attach actions to <button>s like so:
    <button formAction={save}>Save draft</button>
    
  • See also: useActionState, useFormStatus

Upvotes: 2

mehmetdemiray
mehmetdemiray

Reputation: 1126

Shortest way:

onSubmit={(event) => {
  event.preventDefault();
  const formData = new FormData(event.currentTarget);
  const formEntries = Object.fromEntries(formData.entries());
  console.log(formEntries);
}}

Upvotes: 6

ylmzzsy
ylmzzsy

Reputation: 21

If you're using React 18, this approach would make it for you:

export default function Search() {
  function search(e) {
        e.preventDefault();
        console.log("search clicked data = " + e.target[0].value);
  }
  return (
    <form onSubmit={search}>
      <input name="query" />
      <button type="submit">Search</button>
    </form>
  );
}

the official documentation does not work but here is a reference in case in the future they will fix it: https://react.dev/reference/react-dom/components/form#handle-form-submission-on-the-client

Upvotes: 0

Parivallal S
Parivallal S

Reputation: 21

const HandleSubmit = (e) => {
    e.preventDefault();
    let formData = e.target[0].form;
        axios({
            url: 'http://localhost:4000/data/add',
            method: 'POST',
            data: new FormData(formData)
        }).then(async (data) => {
            await toastr.success('Added Successfully', {
                timeOut: 1000,
            });
            await setTimeout(() => {
                window.location.reload();
            }, 1000)

        })
    }

Upvotes: 1

Ibrahim.B
Ibrahim.B

Reputation: 137

TypeScript will complain if you try Aliaksandr Sushkevich's solution. One workaround can be done using type assertions:

<form
    onSubmit={(e: React.SyntheticEvent) => {
      e.preventDefault();
      const target = e.target as typeof e.target & {
        username: { value: string };
        password: { value: string };
      };
      const username = target.username.value; // typechecks
      const password = target.password.value; // typechecks
      // etc...
    }}
>
<input type="text" name="username"/>
...

Though, this is still just a workaround, because here you are telling TypeScript what to expect. This will break at runtime if you add a value that doesn't have a corresponding input element.

Upvotes: 6

Radoslav R&#225;c
Radoslav R&#225;c

Reputation: 53

The simplest solution that came to my mind is this:

<form onSubmit={(e) => handleLogin(e)}>
    <input type="text" name="email" placeholder="Email" />
    <input type="password" name="password" placeholder="Password" />
    <button type="submit">Login</button>
</form>

Your handle fuction:

const handleLogin = (e) => {
    e.preventDefault()
    const data = {
        email: e.target.elements.email.value,
        password: e.target.elements.password.value
    }
    console.log('FormData: ', data)
}

When you click on your login button you will see FormData in console in this format: FormData: {email: 'whatever you tiped here', password: 'also whatever you tiped here'}.

e.target.elements.email.value targets elements with specific name, in your case it is email and password.

After console.log in handleLogin, you can do some verification logic and login logic.

Upvotes: 4

Vikrant
Vikrant

Reputation: 19

<form onSubmit={handleLogin}>
    <input type="text" name="email" placeholder="Email" />
    <input type="text" name="password" placeholder="Password" />
    <button type="submit">Login</button>
</form>
const handleLogin = (event) => {
    event.preventDefault();
    console.log(event.target[0].value)
    console.log(event.target[1].value)
}

Upvotes: 1

E. Fortes
E. Fortes

Reputation: 1338

An easy way to deal with refs:

class UserInfo extends React.Component {

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

  handleSubmit(e) {
    e.preventDefault();

    const formData = {};
    for (const field in this.refs) {
      formData[field] = this.refs[field].value;
    }
    console.log('-->', formData);
  }

  render() {
    return (
        <div>
          <form onSubmit={this.handleSubmit}>
            <input ref="phone" className="phone" type='tel' name="phone"/>
            <input ref="email" className="email" type='tel' name="email"/>
            <input type="submit" value="Submit"/>
          </form>
        </div>
    );
  }
}

export default UserInfo;

Upvotes: 24

Navas Nazar
Navas Nazar

Reputation: 1

Use:

import { useState } from 'react'

export default function App() {
    const [data, setData] = useState({})

    const updateData = e => {
        setData({
            ...data,
            [e.target.name]: e.target.value
        })
    }

    const submit = e => {
        e.preventDefault()
        console.log(data)
    }

    return (
        <form onSubmit={submit}>
            <input
                name="email"
                type="email"
                onChange={updateData}
            />
            <input
                name="password"
                type="password"
                onChange={updateData}
             />
            <button>Submit</button>
        </form>
    )
}

Upvotes: -1

Anis
Anis

Reputation: 1219

For TypeScript users

import react from 'react'

interface FormInterface {
    [key: string]: string
}

const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
   event.preventDefault();
   let formData = new FormData(event.currentTarget)
   let formObj: FormInterface = {}
   for (let [key, value] of Array.from(formData.entries())) {
     formObj[key] = value.toString()
   }
};

<form onSubmit={handleSubmit}>
   <input type="text" name="email" placeholder="Email" />
   <input type="password" name="password" placeholder="Password" />
   <button type="submit">Login</button>
</form>

Upvotes: 7

Adhil mhdk
Adhil mhdk

Reputation: 89

This will be the easiest method:

const formValidator = (form) => {
    let returnData = {}
    console.log(form.length);

    for (let i = 0; i < form.length; i++) {
        const data = form[i]
        if (data.name != null && data.name != "") {
            returnData[data.name] = data.value;
        }
    }
    return returnData
}

In the form, simply use:

<form onSubmit={(e) => {
        e.preventDefault()
        let data = formValidator(e.currentTarget)
    }}>
    <RoundTextFiled name='app-id' style={{ marginTop: '10px', borderRadius: '20px' }} label="App id" fullWidth required />
    <RoundTextFiled name='api-hash' style={{ marginTop: '5px' }} label="Api hash" fullWidth required />
    <RoundTextFiled name='channel-id' style={{ marginTop: '5px' }} label="Channel id" fullWidth required />
    <Button type='submit' variant="contained" fullWidth style={{ padding: '10px', marginTop: '5px', borderRadius: '10px' }}>Login</Button>
</form>

Upvotes: 0

arn48
arn48

Reputation: 340

Here is the shortest way to get data from the form and the best way to avoid id and ref just by using FormData:

import React, { Component } from 'react'

class FormComponent extends Component {
  formSubmit = (event) => {
    event.preventDefault()
    var data = new FormData(event.target)
    let formObject = Object.fromEntries(data.entries())
    console.log(formObject)
  }
  render() {
    return (
      <div>
        <form onSubmit={this.formSubmit}>
          <label>Name</label>
          <input name="name" placeholder="name" />
          <label>Email</label>
          <input type="email" name="email" />
          <input type="submit" />
        </form>
      </div>
    )
  }
}
export default FormComponent

Upvotes: 15

Sameera K
Sameera K

Reputation: 1438

There isn't any need to use refs. You can access it using an event:

function handleSubmit(e) {
    e.preventDefault()
    const {username, password } = e.target.elements
    console.log({username: username.value, password: password.value })
}

<form onSubmit={handleSubmit}>
   <input type="text" id="username"/>
   <input type="text" id="password"/>
   <input type="submit" value="Login" />
</form>

Upvotes: 59

Shapon Pal
Shapon Pal

Reputation: 1146

This is an example of dynamically added fields. Here form data will store by input name key using a React useState hook.

import React, { useState } from 'react'

function AuthForm({ firebase }) {
    const [formData, setFormData] = useState({});

    // On Form Submit
    const onFormSubmit = (event) => {
        event.preventDefault();
        console.log('data', formData)
        // Submit here
    };

    // get Data
    const getData = (key) => {
        return formData.hasOwnProperty(key) ? formData[key] : '';
    };

    // Set data
    const setData = (key, value) => {
        return setFormData({ ...formData, [key]: value });
    };

    console.log('firebase', firebase)
    return (
        <div className="wpcwv-authPage">
            <form onSubmit={onFormSubmit} className="wpcwv-authForm">
                <input name="name" type="text" className="wpcwv-input" placeholder="Your Name" value={getData('name')} onChange={(e) => setData('name', e.target.value)} />
                <input name="email" type="email" className="wpcwv-input" placeholder="Your Email" value={getData('email')} onChange={(e) => setData('email', e.target.value)} />
                <button type="submit" className="wpcwv-button wpcwv-buttonPrimary">Submit</button>
            </form>
        </div>
    )
}

export default AuthForm

Upvotes: 3

hoohoo-b
hoohoo-b

Reputation: 1251

Adding on to Michael Schock's answer:

class MyForm extends React.Component {
  constructor() {
    super();
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleSubmit(event) {
    event.preventDefault();
    const data = new FormData(event.target);

    console.log(data.get('email')); // Reference by form input's `name` tag

    fetch('/api/form-submit-url', {
      method: 'POST',
      body: data,
    });
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label htmlFor="username">Enter username</label>
        <input id="username" name="username" type="text" />

        <label htmlFor="email">Enter your email</label>
        <input id="email" name="email" type="email" />

        <label htmlFor="birthdate">Enter your birth date</label>
        <input id="birthdate" name="birthdate" type="text" />

        <button>Send data!</button>
      </form>
    );
  }
}

See this Medium article: How to Handle Forms with Just React

This method gets form data only when the Submit button is pressed. It is much cleaner, IMO!

Upvotes: 67

Adnan Boota
Adnan Boota

Reputation: 181

I use like this using React Component state:

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

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

Upvotes: 5

Jeff Lowery
Jeff Lowery

Reputation: 2599

If you have multiple occurrences of an element name, then you have to use forEach().

HTML

  <input type="checkbox" name="delete" id="flizzit" />
  <input type="checkbox" name="delete" id="floo" />
  <input type="checkbox" name="delete" id="flum" />
  <input type="submit" value="Save"  onClick={evt => saveAction(evt)}></input>

JavaScript

const submitAction = (evt) => {
  evt.preventDefault();
  const dels = evt.target.parentElement.delete;
  const deleted = [];
  dels.forEach((d) => { if (d.checked) deleted.push(d.id); });
  window.alert(deleted.length);
};

Note the dels in this case is a RadioNodeList, not an array, and is not an Iterable. The forEach() is a built-in method of the list class. You will not be able to use a map() or reduce() here.

Upvotes: 1

Imran Rafique
Imran Rafique

Reputation: 2046

Give your inputs ref like this

<input type="text" name="email" placeholder="Email" ref="email" />
<input type="password" name="password" placeholder="Password" ref="password" />

Then you can access it in your handleLogin like so:

handleLogin: function(e) {
   e.preventDefault();
    console.log(this.refs.email.value)
    console.log(this.refs.password.value)
}

Upvotes: 5

Alireza
Alireza

Reputation: 104870

In many events in JavaScript, we have event which gives an object, including what event happened and what are the values, etc.

That's what we use with forms in React as well.

So in your code you set the state to the new value. Something like this:

class UserInfo extends React.Component {

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

  handleLogin(e) {
    e.preventDefault();
    for (const field in this.refs) {
      this.setState({this.refs[field]: this.refs[field].value});
    }
  }

  render() {
    return (
        <div>
          <form onSubmit={this.handleLogin}>
            <input ref="email" type="text" name="email" placeholder="Email" />
            <input ref="password" type="password" name="password" placeholder="Password" />
            <button type="button">Login</button>
          </form>
        </div>
    );
  }
}

export default UserInfo;

Also this is the form example in React v.16, just as reference for the form you creating in the future:

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

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

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

  handleSubmit(event) {
    alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

Upvotes: 4

ivks
ivks

Reputation: 109

If you are using Redux in your project, you can consider using the higher order component redux-form.

Upvotes: 4

Joe L.
Joe L.

Reputation: 4643

This might help Meteor (v1.3) users:

render: function() {
    return (
        <form onSubmit={this.submitForm.bind(this)}>
            <input type="text" ref="email" placeholder="Email" />
            <input type="password" ref="password" placeholder="Password" />
            <button type="submit">Login</button>
        </form>
    );
},
submitForm: function(e) {
    e.preventDefault();
    console.log( this.refs.email.value );
    console.log( this.refs.password.value );
}

Upvotes: 3

Sachin Som
Sachin Som

Reputation: 1201

Here is my approach for collecting multiple form inputs using single inputChangeHandler

import React from "react";

const COLORS = ["red", "orange", "yellow", "purple", "green", "white", "black"];

export default function App() {

  const initialFormFields = {
    name: undefined,
    email: undefined,
    favourite_color: undefined
  };
  const [formInput, setFormInput] = React.useState(initialFormFields);

  function inputChangeHandler(event) {
    setFormInput(prevFormState => ({
      ...prevFormState,
      [event.target.name]: event.target.value
    }))
  };

  return (
    <div className="App">
      <form>
        <label>Name: <input name="name" type="text" value={formInput.name} onChange={inputChangeHandler}/></label>
        <label>Email: <input name="email" type="email" value={formInput.email} onChange={inputChangeHandler}/></label>
        <div>
          {COLORS.map(color => <label><input type="radio" name="favourite_color" value={color} key={color} onChange={inputChangeHandler}/> {color} </label>)}
        </div>
      </form>

      <div>
        Entered Name: {formInput.name}
        Entered Email: {formInput.email}
        Favourite Color: {formInput.favourite_color}
      </div>
    </div>
  );
}

Upvotes: 0

CloudWave
CloudWave

Reputation: 1095

For those who don't want to use ref and reset the state with OnChange event, you can just use simple OnSubmit handle and loop through the FormData object.

Note that you cannot access formData.entries() directly since it is an iterable, you have to loop over it.

This example is using React Hooks:

const LoginPage = () => {
  const handleSubmit = (event) => {
    const formData = new FormData(event.currentTarget);
    event.preventDefault();
    for (let [key, value] of formData.entries()) {
      console.log(key, value);
    }
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input type="text" name="username" placeholder="Email" />
        <input type="password" name="password" placeholder="Password" />
        <button type="submit">Login</button>
      </form>
    </div>
  );
};

And if you're using TypeScript:

export const LoginPage: React.FC<{}> = () => {
  const handleSubmit: React.FormEventHandler<HTMLFormElement> = (event) => {
    const formData = new FormData(event.currentTarget);
    event.preventDefault();
    for (let [key, value] of formData.entries()) {
      console.log(key, value);
    }
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input type="text" name="username" placeholder="Email" />
        <input type="password" name="password" placeholder="Password" />
        <button type="submit">Login</button>
      </form>
    </div>
  );
};

Upvotes: 76

Sabesan
Sabesan

Reputation: 702

I think this is also the answer that you need. In addition, Here I add the required attributes. onChange attributes of Each input components are functions. You need to add your own logic there.

handleEmailChange: function(e) {
    this.setState({email: e.target.value});
},
handlePasswordChange: function(e) {
   this.setState({password: e.target.value});
},
formSubmit : async function(e) {
    e.preventDefault();
    // Form submit Logic
  },
render : function() {
      return (
        <form onSubmit={(e) => this.formSubmit(e)}>
          <input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleEmailChange} required />
          <input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handlePasswordChange} required />
          <button type="button">Login</button>
        </form>);
},
handleLogin: function() {
    //Login Function
}

Upvotes: 0

jbaiter
jbaiter

Reputation: 7109

Use the change events on the inputs to update the component's state and access it in handleLogin:

handleEmailChange: function(e) {
   this.setState({email: e.target.value});
},
handlePasswordChange: function(e) {
   this.setState({password: e.target.value});
},
render : function() {
      return (
        <form>
          <input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleEmailChange} />
          <input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handlePasswordChange}/>
          <button type="button" onClick={this.handleLogin}>Login</button>
        </form>);
},
handleLogin: function() {
    console.log("EMail: " + this.state.email);
    console.log("Password: " + this.state.password);
}

Working fiddle.

Also, read the docs, there is a whole section dedicated to form handling: Forms

Previously you could also use React's two-way databinding helper mixin to achieve the same thing, but now it's deprecated in favor of setting the value and change handler (as above):

var ExampleForm = React.createClass({
  mixins: [React.addons.LinkedStateMixin],
  getInitialState: function() {
    return {email: '', password: ''};
  },
  handleLogin: function() {
    console.log("EMail: " + this.state.email);
    console.log("Password: " + this.state.password);
  },
  render: function() {
    return (
      <form>
        <input type="text" valueLink={this.linkState('email')} />
        <input type="password" valueLink={this.linkState('password')} />
        <button type="button" onClick={this.handleLogin}>Login</button>
      </form>
    );
  }
});

Documentation is here: Two-way Binding Helpers.

Upvotes: 226

Sergio Ivanuzzo
Sergio Ivanuzzo

Reputation: 1922

More clear example with es6 destructing

class Form extends Component {
    constructor(props) {
        super(props);
        this.state = {
            login: null,
            password: null,
            email: null
        }
    }

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

    onSubmit(e) {
        e.preventDefault();
        let login = this.state.login;
        let password = this.state.password;
        // etc
    }

    render() {
        return (
            <form onSubmit={this.onSubmit.bind(this)}>
                <input type="text" name="login" onChange={this.onChange.bind(this)} />
                <input type="password" name="password" onChange={this.onChange.bind(this)} />
                <input type="email" name="email" onChange={this.onChange.bind(this)} />
                <button type="submit">Sign Up</button>
            </form>
        );
    }
}

Upvotes: 6

Aral Roca
Aral Roca

Reputation: 5929

If all your inputs / textarea have a name, then you can filter all from event.target:

onSubmit(event){
  const fields = Array.prototype.slice.call(event.target)
      .filter(el => el.name)
      .reduce((form, el) => ({
        ...form,
        [el.name]: el.value,
      }), {})
}

Totally uncontrolled form 😊 without onChange methods, value, defaultValue...

Upvotes: 17

Milan Panigrahi
Milan Panigrahi

Reputation: 546

 onChange(event){
     console.log(event.target.value);
  }
  handleSubmit(event){ 
    event.preventDefault();
    const formData = {};
      for (const data in this.refs) {
        formData[data] = this.refs[data].value;
      }
    console.log(formData);
  }



 <form onSubmit={this.handleSubmit.bind(this)}>
  <input type="text" ref="username" onChange={this.onChange} className="form-control"/>
  <input type="text" ref="password" onChange={this.onChange} className="form-control"/>
  <button type="submit" className="btn-danger btn-sm">Search</button>
 </form>

Output image attached here

Upvotes: 3

Aliaksandr Sushkevich
Aliaksandr Sushkevich

Reputation: 12384

There are a few ways to do this:

1) Get values from array of form elements by index

handleSubmit = (event) => {
  event.preventDefault();
  console.log(event.target[0].value)
}

2) Using name attribute in html

handleSubmit = (event) => {
  event.preventDefault();
  console.log(event.target.elements.username.value) // from elements property
  console.log(event.target.username.value)          // or directly
}

<input type="text" name="username"/>

3) Using refs

handleSubmit = (event) => {
  console.log(this.inputNode.value)
}

<input type="text" name="username" ref={node => (this.inputNode = node)}/>

Full example

class NameForm extends React.Component {
  handleSubmit = (event) => {
    event.preventDefault()
    console.log(event.target[0].value)
    console.log(event.target.elements.username.value)
    console.log(event.target.username.value)
    console.log(this.inputNode.value)
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input
            type="text"
            name="username"
            ref={node => (this.inputNode = node)}
          />
        </label>
        <button type="submit">Submit</button>
      </form>
    )
  }
}

Upvotes: 412

Yurii Kosygin
Yurii Kosygin

Reputation: 57

Also, this can be used too.

handleChange: function(state,e) {
  this.setState({[state]: e.target.value});
},
render : function() {
  return (
    <form>
      <input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleChange.bind(this, 'email')} />
      <input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handleChange.bind(this, 'password')}/>
      <button type="button" onClick={this.handleLogin}>Login</button>
    </form>
  );
},
handleLogin: function() {
  console.log("EMail: ", this.state.email);
  console.log("Password: ", this.state.password);
}

Upvotes: 4

Related Questions