Home > Back-end >  Reactjs Object State Change Events in Form
Reactjs Object State Change Events in Form

Time:07-01

So I've got a basic form that I'm rendering and the component needs state. I would prefer for the state to be an object instead of a list of values so I can easily call JSON.stringify(stateObject). This would enable me to easily refactor into a more re-usable HOC later where I pass the state object definition & urls as a configuration.

Anyways, what happens is that every time I modify an input, it clears out the properties which were not changed and sets the property which was changed.

See initial entry below

Initial Entry

I add input to a different input and it removes the first input and adds the second input. Notice that Facility Name is now cleared and address is now populated.

enter image description here

Below is the code which is doing this

import React, { useState } from "react";
import { Form, Row, Col, Button, Container } from "react-bootstrap";

function FacilitiesCreate() {
  const [Name, setName] = useState("");//not ideal
  const [Latitude, setLatitude] = useState("");//not ideal
  const [Longitude, setLongitude] = useState("");//not ideal
  const [Description, setDescription] = useState("");//not ideal
  const [AddressLineOne, setAddressLineOne] = useState("");//not ideal
  const [AddressLineTwo, setAddressLineTwo] = useState("");//not ideal
  const [City, setCity] = useState("");//not ideal
  const [State, setState] = useState("");//not ideal
  const [ZipCode, setZipCode] = useState(""); //not ideal
  const [Facility, setFacility] = useState({
    Name: "",
    Latitude: 0,
    Longitude: 0,
    Description: "",
    AddressLineOne: "",
    AddressLineTwo: "",
    City: "",
    State: "",
    ZipCode: "",
  }); //I want to be able to JSON.stringify this for my body post call :D see handleSubmit
  
    const createFacilityEndpoint = "https://localhost:7113/api/facilities";
    
      const handleSubmit = async (event) => {
          event.preventDefault();
          let response = await fetch(createFacilityEndpoint, {
            method: "POST",
            headers: {
              "Content-Type": "application/json;charset=utf-8",
            },
            body: JSON.stringify(Facility),
          });
          if (response.ok) {
            alert("YAY!");
          }
      };
  return (
    <Container>
      <h2>Create New Facility</h2>
      <p>facility name: {Facility.Name}</p>
      <br></br>
      <p>address: {Facility.AddressLineOne}</p>
      <Form onSubmit={handleSubmit}>
        <Row className="mb-3">
          <Col>
            <Form.Label>Location Name</Form.Label>
            <Form.Control
              type="text"
              placeholder="Location's Name"
              onChange={(e) => setFacility({ Name: e.target.value })}
            />
          </Col>

          <Col>
            <Form.Label>Latitude</Form.Label>
            <Form.Control
              type="float"
              placeholder="Enter Latitude"
              onChange={(e) => setLatitude(e.target.value)}
            />
          </Col>

          <Col>
            <Form.Label>Longitude</Form.Label>
            <Form.Control
              type="float"
              placeholder="Enter Longitude"
              onChange={(e) => setLongitude(e.target.value)}
            />
          </Col>
        </Row>
        <Row className="mb-3">
          <Col>
            <Form.Label>Description</Form.Label>
            <Form.Control
              as="textarea"
              rows={3}
              placeholder="Enter Description"
              onChange={(e) => setDescription(e.target.value)}
            />
          </Col>
        </Row>

        <Form.Group className="mb-3" controlId="formGridAddress1">
          <Form.Label>Address</Form.Label>
          <Form.Control
            placeholder="1234 Main St"
            onChange={(e) => setFacility({ AddressLineOne: e.target.value })}
          />
        </Form.Group>

        <Form.Group className="mb-3" controlId="formGridAddress2">
          <Form.Label>Address 2</Form.Label>
          <Form.Control
            placeholder="Apartment, studio, or floor"
            onChange={(e) => setAddressLineTwo(e.target.value)}
          />
        </Form.Group>

        <Row className="mb-3">
          <Form.Group as={Col} controlId="formGridCity">
            <Form.Label>City</Form.Label>
            <Form.Control
              placeholder="Miami Beach"
              onChange={(e) => setCity(e.target.value)}
            />
          </Form.Group>

          <Form.Group as={Col} controlId="formGridState">
            <Form.Label>State</Form.Label>
            <Form.Control
              placeholder="FL"
              onChange={(e) => setState(e.target.value)}
            />
          </Form.Group>

          <Form.Group as={Col} controlId="formGridZip">
            <Form.Label>Zip</Form.Label>
            <Form.Control
              placeholder="33141"
              onChange={(e) => setZipCode(e.target.value)}
            />
          </Form.Group>
        </Row>

        <Button variant="primary" type="submit">
          Submit
        </Button>
      </Form>
    </Container>
  );
}

export default FacilitiesCreate;

So the above is kinda cool, except it keeps nuking the other properties in the Facility State object...

CodePudding user response:

Change the following:

(e) => setFacility({ Name: e.target.value })

to:

(e) => setFacility((oldValue) => ({ ...oldValue, Name: e.target.value }))

There is an option with useState to provide a callback function to the set function. This callback gets the old value of the state as parameter, so you can use it for the new state you want to set.

  • Related