1

When IDs are generated in a server for documents, how can the frontend send HTTP Delete requests properly? Since HTTP Delete requests require a document's ID to route to the server, but IDs are generated in the server, how can the frontend know the IDs generated?

In my server:

let persons = [ // my "database"
    {
    "name": "Arto Hellas",
    "number": "040-123456",
    "id": 1
    },
    {
    "name": "test1",
    "number": "111-111-1111",
    "id": 4168 //GENERATED AFTER RECEIVING AN HTTP POST REQUEST
    },
    {
    "name": "test2",
    "number": "222-222-2222",
    "id": 839 //GENERATED AFTER RECEIVING AN HTTP POST REQUEST
    }

];

app.delete('/api/persons/:id', (req,res) => {
    let id = Number(req.params.id);
    persons = persons.filter(person => person.id !== id);
    res.json(persons);
});

const generateId = () => {
    return Math.floor(Math.random() * 10000); //0 to 9999
}

app.post('/api/persons', (req,res) => {
    let body = req.body;

    let newPerson = {
        name: body.name,
        number: body.number,
        id: generateId()
    }

    persons = persons.concat(newPerson);
    res.json(persons);
});

When my frontend creates an HTTP Post request to the backend, it sends a Name and Number. The backend receives the Post request, and creates a JS object with the Name, Number, and also generates an ID for it, then appends it to my array "database".

Here is my React component in question with deletion capability,

const PhoneBookEntry = ({ name, number, persons, setPersons}) => {

    const deletePerson = () => {
        phonebookComm
            .delPerson(id) // *** how can my frontend determine the IDs generated in the backend?
            .then( res => {
                //updating my application's persons state
                persons.splice(persons.findIndex(element => element.name === name), 1 ); 
                setPersons(persons.map(person => person.name !== name ? person : null));                                                    
            })
            .catch( error => {
                console.log('error', error);
            })
    }

    return (
        <div>
            <div className="personAndDelBtn">{name} {number} </div>
            <button className="personAndDelBtn" onClick={deletePerson}>delete</button>
        </div>
    );
}

Where phonebookComm uses axios:

const delPerson = id => {
    return axios.delete(`${baseUrl}/${id}`).then(res => res.data);
}

How can I get IDs from the backend, for HTTP Delete requests in the frontend?

Since the backend generates the ID for each document, the frontend doesn't know a document's ID. When the frontend needs to send an HTTP Delete request, how can it know what ID to use?

Brendan
  • 752
  • 1
  • 8
  • 21

2 Answers2

2

You probably need to update your newly created user after the POST request succeeds: you have the id since the backend sends you the newly created user in the POST response (with the id):

app.post('/api/persons', (req,res) => {
    let body = req.body;

    let newPerson = {
        name: body.name,
        number: body.number,
        id: generateId()
    }

    persons = persons.concat(newPerson);
    res.json(persons);
});
giuseppedeponte
  • 2,366
  • 1
  • 9
  • 19
  • The IDs generated in the server can be returned to the frontend through res.json(persons). Persons in the backend contained the IDs which is sent back as a res to the frontend. I was not using the responses from my server! I implemented them, but in trying to bridge the frontend and backend together, I missed utilizing the res.json. I set my React Hook state, representing the list of persons, with the res, updating the frontend's list of persons with the IDs generated from the server. – Brendan Oct 19 '19 at 06:12
1

Your PhoneBookEntry component is a row in the persons list, isn't it? A think, you must have some way to get this person's list from your server. Something like this:

app.get('/api/persons', (req,res) => {
    res.json(persons);
});

You should reload the persons list from server after every editing action like deletion. It's not good idea to manage local database and server database similarly.

My suggestion is move deletion method from the PhoneBookEntry component.

const PhoneBookEntry = ({ name, number, onDelete}) => {
    return (
        <div>
            <div className="personAndDelBtn">{name} {number} </div>
            <button className="personAndDelBtn" onClick={onDelete}>delete</button>
        </div>
    );
}

And define delete and fetch methods in the top level component (person's list). I'm using React Hooks useState useCallback and useEffect. They are great, try them on!

const PhoneBook = () => {

// book state
    const [list, setList] = useState([]);
// loading flag
    const [loading, setLoading] = useState(true);

    const fetch = useCallback(() => fetchPersons().then((res) => setList(res), [])

    const deletePerson = useCallback((id) => delPerson(id).then(() => fetch()), [])

//this will run fetch after the component was mounted and rendered in the first time
    useEffect(() => {
        fetch().then(() => setLoading(false))
    }, [])

    if (loading) {
        return <div>Loading contacts... </div>
    }

    return <ul>
        {list.map((person) => {
            return <li>
                <PhoneBookEntry name={person.name} number={person.number} onDelete={() => deletePerson(person.id)}
                                key={person.id}/>
            </li>
        })}
    </ul>

}

You can define the fetch method like this

const fetch = () => axios.get(`${baseUrl}`)
Bragnikita
  • 41
  • 1
  • 4