Skip to content
Advertisement

React : Empty values on PUT for axios

I have a simple list that I get from an API using axios. Every element is a modifiable input, with it own update button.

After changing the data of an input, and while performing PUT request, console.log(test); returns empty values.

I checked console.log(newList); which is the array of the list, and the changing data are indeed happening in the list, but it seems they can’t be sent to the server.

Note : The API is just for testing, the PUT method may not work, but atleast the values in the console should be sent.

Note2 : I don’t know how to place the id of an item of the list in the url so you may encounter an error. / You can try with 1,2 or 3 instead for testing.

https://codesandbox.io/s/quizzical-snowflake-dw1xr?file=/src/App.js:1809-1834

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

export default () => {
  const [list, setList] = React.useState([]);
  const [name, setName] = React.useState("");
  const [description, setDescription] = React.useState("");
  const [city, setCity] = React.useState("");

  // Getting initial list from API
  useEffect(() => {
    axios
      .get("https://6092374385ff5100172122c8.mockapi.io/api/test/users")
      .then((response) => {
        setList(response.data);
        console.log(response);
      })
      .catch((err) => console.log(err));
  }, []);

  // onUpdate to update the data in the API
  const onUpdate = (e) => {
    e.preventDefault();

    const test = {
      name: name,
      description: description,
      city: city
    };

    console.log(test);

    // axios request PUT data on API
    axios
      .put(
        "https://6092374385ff5100172122c8.mockapi.io/api/test/users" + id,
        test
      )
      .then((res) => {
        alert("success");
        console.log(res);
      })
      .catch((error) => {
        console.log(error);
      });

    // axios request GET to get the new modified list from the database, after the update
    axios
      .get("https://6092374385ff5100172122c8.mockapi.io/api/test/users")
      .then((res) => {
        alert("success");
        console.log(res);
      })
      .catch((error) => {
        console.log(error);
      });
  };

  // Handler for changing values of each input
  function handleChangeUpdate(id, event) {
    const { name, value } = event.target;
    const newList = list.map((item) => {
      if (item.id === id) {
        const updatedItem = {
          ...item,
          [name]: value
        };

        return updatedItem;
      }
      return item;
    });
    setList(newList);
    console.log(newList);
  }

  return (
    <div>
      <ul>
        <div>
          {list.map((item) => (
            <li key={item.id}>
              <input
                className="form-control"
                name="name"
                onChange={(event) => handleChangeUpdate(item.id, event)}
                defaultValue={item.name}
              ></input>

              <input
                className="form-control"
                name="description"
                onChange={(event) => handleChangeUpdate(item.id, event)}
                defaultValue={item.description}
              ></input>

              <input
                className="form-control"
                name="city"
                onChange={(event) => handleChangeUpdate(item.id, event)}
                defaultValue={item.city}
              ></input>

              <button onClick={onUpdate}>Update</button>
            </li>
          ))}
        </div>
      </ul>
    </div>
  );
};

Answer

It’s because you never set the values of the props. That is why they never change from their initial values. You just update the list prop in handleChangeUpdate. There are two steps you need to take with the existing file structure:

  1. Make handleChangeUpdate be able to differentiate between different props (city, description, etc.). For example, by passing the prop’s name.
  2. Update the prop’s value in the handleChangeUpdate.

To realize the first step, you can change the input tag like the following:

{/* attention to the first argument of handleChangeUpdate */}
<input
    className="form-control"
    name="name"
    onChange={(event) => handleChangeUpdate("name", item.id, event)}
    defaultValue={item.name}
></input>

Then, you need to adjust the handleChangeUpdate:

if (name === "name") {
    setName(value);
} else if (name === "description") {
    setDescription(value);
} else if (name === "city") {
    setCity(value);
}

By the way, list is not a good name for a variable.

Alternatively

Without creating new parameters, you can also use only the event to set the props

  // Handler for changing values of each input
  function handleChangeUpdate(id, event) {
    const { name, value } = event.target;
    const newList = list.map((item) => {
      if (item.id === id) {
        const updatedItem = {
          ...item,
          [name]: value
        };

        return updatedItem;
      }
      return item;
    });
    setList(newList);
    console.log(newList);

    if (name === "name") {
      setName(value);
    } else if (name === "description") {
      setDescription(value);
    } else if (name === "city") {
      setCity(value);
    }
  }

Advertisement