5hakir
5hakir

Reputation: 129

Can not change state while trying to update value

I'm new to react and i am creating an employee form where i have to send gender info into JSON format. initialstate

constructor(){

    super()
    this.state ={
        gender:{
            gender:""
        },
 }

Here i defined my initial state . handleChange event part

handleChange(event) {
    const {name, value, type, checked} = event.target
    type === "checkbox" ? this.setState({ [name]: checked }) : this.setState({ [name]: value })
}

i am handling checkbox type data here to update value of current state. here is the handle submit part. I have to send data to an API in this format

gender: {
gender:"male"
}
handleSubmit(event) {

    event.preventDefault();

        const obj = this.state

        console.log(this.obj)
        axios.post('https://jsonplaceholder.typicode.com/posts',this.state)

  }

form part

 <div className="form-group">
       <label for="gender">Gender:</label>
            <div className="radio" style={genderRadio}>
                   <label>
                     <input type="radio" value="male" checked={this.state.gender.gender === "male"} onChange={this.handleChange} name="gender"  />Male</label>

              </div>
             <div className="radio">
                   <label>
                      <input type="radio"  value="female" checked={this.state.gender.gender === "female"} onChange={this.handleChange} name="gender"/>Female</label>
             </div>
             <div className="radio ">
                <label>
                   <input type="radio"  value="others" checked={this.state.gender.gender === "others"} onChange={this.handleChange} name="gender" />Others</label>
             </div> 


  </div>

Upvotes: 0

Views: 140

Answers (3)

Tharik Ajis
Tharik Ajis

Reputation: 1

Your problem is with updating the state. Try the following alternative.

** Current:**

handleChange(event) {
    const {name, value, type, checked} = event.target
    type === "checkbox" ? this.setState({ [name]: checked }) : this.setState({ 
   [name]: value })
}

**Solution:**

constructor(props){
    super(props)
    this.state ={
        data:{
            gender:""
        },
 }

handleChange(event) {
    const {name, value, type, checked} = event.target
    this.setState({
         data:{
           [name]: type =="checkbox" ? checked : value
         }
    })

}

Upvotes: 0

Cat_Enthusiast
Cat_Enthusiast

Reputation: 15698

First of all you need to bind the this keyword inside your handleChange function so that it points to the component's execution context.

Either explicitly bind it in your constructor, or use an arrow-function. If you don't then, the this keyword will be undefined and therefore you cannot use this.setState()

Additionally, you have a a gender object with its own field called gender in your component-state. There are two levels of data you need to account for. So updating the inner-gender value will not be as simple as doing this this.setState({ [name]: checked })

See working sandbox here: https://codesandbox.io/s/elated-maxwell-piobv

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      gender: {
        gender: ""
      }
    };
  }
  handleChange = event => {
    const { name, value, type, checked } = event.target;
    if (type !== "checkbox") {
      this.setState(
        {
          [name]: {
            ...this.state[name],
            [name]: value
          }
        }
      );
    }
  };

  handleSubmit(event) {
    event.preventDefault();

    const obj = this.state;

    console.log(this.obj);
    // axios.post("https://jsonplaceholder.typicode.com/posts", this.state);
  }
  render() {
    return (
      <div className="form-group">
        <label for="gender">Gender:</label>
        <div className="radio">
          <label>
            <input
              type="radio"
              value="male"
              checked={this.state.gender.gender === "male"}
              onChange={this.handleChange}
              name="gender"
            />
            Male
          </label>
        </div>
        <div className="radio">
          <label>
            <input
              type="radio"
              value="female"
              checked={this.state.gender.gender === "female"}
              onChange={this.handleChange}
              name="gender"
            />
            Female
          </label>
        </div>
        <div className="radio ">
          <label>
            <input
              type="radio"
              value="others"
              checked={this.state.gender.gender === "others"}
              onChange={this.handleChange}
              name="gender"
            />
            Others
          </label>
        </div>
      </div>
    );
  }
}

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

Upvotes: 0

Muljayan
Muljayan

Reputation: 3886

Change your onChange handler as follows

      handleChange(event) {
            const {name, value, type, checked} = event.target
            if(type === "checkbox"){
              this.setState({ [name]: checked })
            } else {
              if(name=== "gender"){
                this.setState({ gender: { gender: value });
              } else {
                this.setState({ [name]: value })
              }
            }
        }

The issue arises because you are nesting gender inside another gender object.

Upvotes: 1

Related Questions