1

I'm working on the CRUD operations that are to be performed in an application using JSON placeholder API. I want to update the data of the API using the PUT request and display it back on my front end. I'm actually fetching the data from the users endpoint. I'm not able to perform the PUT request and I'm not understanding whether or not to set the array after performing the PUT request. I keep getting an error that is: userData.map() is not a function after clicking on save changes. I know that I'm setting a single object to the array after the fetching operation which is logically incorrect. I'm using Axios at present, also used fetch(), but no use. Nothing works! Please help me out with this one. I'm attaching the code below. "handleSave" is the function where I'm performing the changes.

Thank you very much in advance!

    import React, { useState, useEffect } from 'react';
    import { v4 as uuidv4 } from 'uuid';
    import axios from 'axios';

    function Table() {

    const [userData, setUserData] = useState([]);
    const [clickOnEdit, setClickOnEdit] = useState(false);
    const [index, setIndex] = useState("");
    const [name, setName] = useState("")
    const [username, setUsername] = useState("")
    const [email, setEmail] = useState("")
    const [phone, setPhone] = useState("")
    const [website, setWebsite] = useState("")

    useEffect(() => {
        axios.get("https://jsonplaceholder.typicode.com/users").then((res) => {
        setUserData(res.data);
    })
    },[])

    const handleAddRow = () => {
        setUserData([...userData, 
            {
                id: uuidv4(), 
                name: "name", 
                username: "username",
                email: "email",
                phone: "phone",
                website: "website"
            }
        ])
    }

    const handleDelete = (item) => {
        const id = item;
        setUserData(userData.filter((individualItem) => individualItem.id !== id));
    }

    const handleEdit = (item) => {
        const id = item;
        setIndex(id);
        setClickOnEdit(true);
    }


    const handleSave = (item) => {

        setClickOnEdit(false);
        axios.put(`https://jsonplaceholder.typicode.com/users/${item}`,
        {
            name: name, 
            username: username, 
            email: email, 
            phone: phone, 
            website: website
        })
        .then((res) => {
            setUserData(res.data);
        })
    }

    return (
        <div>
            <div>
                <table>
                    <tr>
                        <th>Name</th>
                        <th>Username</th>
                        <th>Email</th>
                        <th>Phone</th>
                        <th>Website</th>
                    </tr>
                </table>
            </div>
            <button onClick={(e) => handleAddRow(e)}>Add row</button>
            {userData.map((items, id) => (
                <div key={id} >
                    <table>
                        <tr>
                            {clickOnEdit ? 
                                <div>
                                    {index === id ?
                                    <div>
                                        <td><input value={name} name="name" onChange={(e) => setName(e.target.value)} /></td>
                                        <td><input value={username} name="username" onChange={(e) => setUsername(e.target.value)} /></td>
                                        <td><input value={email} name="email" onChange={(e) => setEmail(e.target.value) } /></td>
                                        <td><input value={phone} name="phone" onChange={(e) => setPhone(e.target.value)} /></td>
                                        <td><input value={website} name="website" onChange={(e) => setWebsite(e.target.value)} /></td>
                                        <button onClick={() => handleSave(items.id)} >Save entry</button>
                                    </div>
                                    :
                                    <div>
                                        <td>{items.name}</td>
                                        <td>{items.username}</td>
                                        <td>{items.email}</td>
                                        <td>{items.phone}</td>
                                        <td>{items.website}</td>
                                        <button onClick={(e) => handleEdit(items.id, e)} >Edit</button>
                                        <button onClick={() => handleDelete(items.id)}>Delete</button>
                                    </div>
                                    }
                                </div>
                                :
                                <div>
                                    <td>{items.name}</td>
                                    <td>{items.username}</td>
                                    <td>{items.email}</td>
                                    <td>{items.phone}</td>
                                    <td>{items.website}</td>
                                    <button onClick={(e) => handleEdit(items.id, e)} >Edit</button>
                                    <button onClick={() => handleDelete(items.id)}>Delete</button>
                                </div>
                            }
                        </tr> 
                    </table>
                </div>
            ))}
        </div>
    )
}

export default Table;

2 Answers2

2

The response you will get is an object, so try to replace that id with the res object.

 const handleSave = (item) => {

        setClickOnEdit(false);
        axios.put(`https://jsonplaceholder.typicode.com/users/${item}`,
        {
            name: name, 
            username: username, 
            email: email, 
            phone: phone, 
            website: website
        })
        .then((res) => {
          setUserData(
            userData.map((user) =>
              user.id === res.data.id - 1 ? res.data : user
            )
          );
        })
    }
Badal Saibo
  • 2,499
  • 11
  • 23
  • I made the changes sir. Am I doing anything wrong within the entire
    section? Although there is no error, the logic doesn't work..
    – kavili vishnu Jul 15 '21 at 05:02
  • Whoaa!! Thank you very much sir! It worked! I'll try to understand the logic. Can I please contact you if I had any doubts in the coming days? – kavili vishnu Jul 15 '21 at 05:20
  • You're implementation is really messy. Try to have a unique id. I did `res.data.id - 1` which was a hack to get to the right element. Try getting to the right element first with proper ids without the hack. Next, try to clear off all the warnings on the console. You'll learn a lot just by clearing those console warnings. – Badal Saibo Jul 15 '21 at 05:25
  • Got it sir! I was trying to pinpoint the item that I wanted to work with, but wasn't able to reach that point. – kavili vishnu Jul 15 '21 at 05:28
1

First thing - You should always check the status code of your response. I mean if it is success then what status code it returns Normally get request gives 200. If you do not check it then If error occurs then It will also execute the below line

setUserData(res.data);

Secondly as the userData is an array so you should set the updated response like below after the put

setUserData([...userData.filter(element => element.id === res.data.id - 1 ? res.data : element)])
moshfiqrony
  • 4,303
  • 2
  • 20
  • 29