Sagun Raj Lage
Sagun Raj Lage

Reputation: 2514

Empty value when form is submitted for the first time

I have the following code which is intended to get the input fed to ToggleForm component (which is a form) and store it in employeeData state. However, the problem is that whenever I press the submit button of ToggleForm for the first time after execution, "" value gets stored first in the employeeData state and it is only after I click the submit button for the second time that the data fed in the form comes to employeeData.

This must be a minor mistake. But I am not being able to figure it out.

import React from "react";
import ToggleForm from "./ToggleForm";
let employee = "";
class Home extends React.Component {
  constructor(){
    super();
    this.state = {
        employeeData: ""
      };
  }

addEmployee(e) {
    e.preventDefault();
    let name = e.target.name.value;
    let address = e.target.address.value;
    let salary = e.target.salary.value;  
    this.setState({
        employeeData: [...this.state.employeeData, { name, address, salary }]
      });
    employee = [...this.state.employeeData];
    console.log(employee);
  }

render() {
    return (
      <div className="container">
          <ToggleForm addEmployee={this.addEmployee.bind(this)}/>
      </div>
    );
  }
}

export default Home;

Here is the ToggleForm component:

import React from 'react';

class ToggleForm extends React.Component {
    render(){
        return(<div>
            <br/>
                <h3>Add a new employee</h3>
                <hr/>
                <form className="form-group" onSubmit = {this.props.addEmployee}>
                    <input className="form-control" type="text" name="name" placeholder="Name of the employee"/><br/>
                    <input className="form-control" type="text" name="address" placeholder="Address of the employee"/><br/>
                    <input className="form-control" type="text" name="salary" placeholder="Salary of the employee"/><br/>
                    <input type="submit" className="btn btn-primary"/>
                </form>
        </div>)
    }
}

export default ToggleForm;

Upvotes: 2

Views: 2033

Answers (3)

Piyush Zalani
Piyush Zalani

Reputation: 3934

There are few basic correction in your components: User super(); in the constructor before this.setState();

If you are not using this.state.employeeData, then don't set it in the state.

If you set the state then you will get the employeeData in the callback function as described by @Andy or you can use the following:

employee = [...this.state.employeeData, { name, address, salary }]

Upvotes: 0

Tony Bui
Tony Bui

Reputation: 1299

Because setState is async so your need to setState in the component Toggle form when the text is change before ship it the parent component.

For example:

<input
onChange={this.handleChange}
className="form-control"
type="text"
name="name"
value={this.state.name}
placeholder="Name of the employee"
/>
<br />

Function handleChange:

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

And then ship it to the parent:

 handleSubmit = e => {
    e.preventDefault();
    const { name, address, salary } = this.state;
    this.props.addEmployee({ name, address, salary });
  };

Check my code here: https://codesandbox.io/s/ww5331jrxl

Upvotes: 1

Andy Hoffman
Andy Hoffman

Reputation: 19109

setState is async and fortunately accepts an optional callback. Using the callback, you can access the most current value of state.

this.setState({
  employeeData: [...this.state.employeeData, { name, address, salary }]
}, () => { 
  employee = [...this.state.employeeData];
});

Upvotes: 2

Related Questions