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> ); };
Advertisement
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:
- Make handleChangeUpdate be able to differentiate between different props (city, description, etc.). For example, by passing the prop’s name.
- 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); } }