Home > Software design >  React Function Component Form not setting state variables?
React Function Component Form not setting state variables?

Time:11-10

I have a React Function Component that is a form where users enter in values. The user inputs are stored using Hooks. The issue that I am running into is that it does not seem to be setting the hook correctly. When I console log one value right before the axios call, it returns as undefined. Below is the code I have so far. I think I am pretty close but am unsure where I made mistakes. Any help is appreciated!

import React, { useState, useEffect } from "react";
import axios from "axios";

function ReportOutage(){
    //Use state hook to hold the values users input, passed into axios call
    //setting the default values
    const [formData, setFormData] = useState({
        userReport: '6',
        serviceType: "",
        serviceName: "",
        serviceStreet: "",
        serviceCity: "",
        serviceState: "",
        serviceDescription: ""
    }) 

    const handleChange = (event) => {
        event.preventDefault();
        setFormData({[event.target.name]: event.target.value})
    };

    const handleSubmitReport = async (event) =>{
        event.preventDefault();
        console.log(formData.serviceName); // This is returning undefined when I am expecting the service name entered by the user.
        const res = await axios.post("/outage-new", {
            user_id: `${formData.userReport}`,
            service_type: `${formData.serviceType}`,
            service_name: `${formData.serviceName}`,
            outage_street: `${formData.serviceStreet}`,
            outage_city: `${formData.serviceCity}`,
            outage_state: `${formData.serviceState}`,
            outage_description: `${formData.serviceDescription}`,
        })
    };

    return (
        <>
            <h1 id="Report-Title" class>Test Dialog box</h1>
            <form onSubmit={handleSubmitReport}>
                <input type="text" placeholder="Service Type" 
                onChange={handleChange}
                value={formData.serviceType}
                name="serviceType"/>

                <input type="text" placeholder="Service Name"
                onChange={handleChange} 
                value={formData.serviceName}
                name="serviceName"/>

                <input type="text" placeholder="Street"
                onChange={handleChange} 
                value={formData.serviceStreet}
                name="serviceStreet"/>

                <input type="text" placeholder="City"
                onChange={handleChange} 
                value={formData.serviceCity}
                name="serviceCity"/>

                <input type="text" placeholder="State"
                onChange={handleChange} 
                value={formData.serviceState}
                name="serviceState"/>

                <input type="text" placeholder="Description"
                onChange={handleChange} 
                value={formData.serviceDescription}
                name="serviceDescription"/>

                <button type="submit">Report Outage</button>
            </form>
        </>
    );
}

export default ReportOutage;

CodePudding user response:

When using the useState hook, updates are not shallowly merged like they are in the class component's this.setState. You are replacing the state with a new object with only the last field value updated.

const handleChange = (event) => {
  event.preventDefault();
  setFormData({ // <-- new object with only field name/value
    [event.target.name]: event.target.value
  });
};

You must manage this yourself, manually. Use a functional state update to access and shallow copy the previous state into the next state object.

const handleChange = (event) => {
  event.preventDefault();
  const { name, value } = event.target;
  setFormData(data => ({
    ...data,
    [name]: value,
  }));
};
  • Related