DEV Community

Issac Lewkowicz
Issac Lewkowicz

Posted on

CRUD and Event Handling in React

Fetching in react

Fetching in React is similar to fetching in JavaScript.
The way we handle those requests is different due to State hooks and the way we render things to the DOM.

Note: I will be using a pessimistic approach to rendering elements - by only updating state from successful fetches.

CRUD requests

GET

In react, we cannot simply have our fetch request in a function.
If we do that, the page will re-render in an infinite loop of:

component rendering → fetch → data is set to state → state update triggers a re-render → re-render triggers another fetch -> the fetch updates state -> re-render → infinite loop.

Instead, we can use a {useEffect} hook for our GET to render once, and the empty dependency array will make sure it won't re-render.

useEffect(() => {
  fetch('fetchURL')
      .then(response => response.json())
      .then(data => setState(data))
  }, [])
Enter fullscreen mode Exit fullscreen mode

POST

We can handle post requests by having a handler function receive the return data.
Here's an example of a form submitting Component:

import React, { useState } from "react";

function NewItemForm({ onAddItem }) {

    const defaultFormData = {
        example1: "",
        example2: ""
    }

    const [formData, setFormData] = useState(defaultFormData)

    const updateFormData = (e) => {
        const { name, value } = e.target;
        setFormData({ ...formData, [name]: value });
    };

    const handleSubmit = (e) => {
        e.preventDefault();

        const postConfig = {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "Accept": "application/json"
            },
            body: JSON.stringify(formData),
        };

        fetch('fetchURL/Items', postConfig)
            .then(response => response.json())
            .then((newItem => {
                onAddItem(newItem);
                setFormData(defaultFormData);
            }))
    }

    return (
        <form onSubmit={handleSubmit} >
            <input onChange={updateFormData} name="example1" value={formData.example1} />
            <input onChange={updateFormData} name="example2" value={formData.example2} />
            <input type="submit" value="Submit" />
        </form>
    );
}

export default NewItemForm;

Enter fullscreen mode Exit fullscreen mode

For POST we would usually want to concatenate the new data to the existing data array.
So we need to be aware to not overwrite the existing data. Fortunately, we have the spread operator to help us out.

This is an example of how our handler handleNewItem (what onAddItem is called in the parent component) may look like:

const handleNewItem = (newItem) => {
const updatedItemList = [...itemList, newItem];
setItemList(updatedItemList)
}
Enter fullscreen mode Exit fullscreen mode

By using this method, we avoid changing the state array directly (a subject worthy of it's own blog post) and update our array with the new item.

PATCH

PATCH requests are similar to POST requests.
This time we will use the .map array method to update our array in our state. This is our way of updating a specific element in our data array.

function handleUpdateItem(newItem) {
    const updatedItems = items.map(item => 
        item.id === newItem.id ? newItem : item)
    setItems(updatedItems)
}

const patchConfig = {
  method: "PATCH",
  headers: {
    "Content-Type": "application/json",
    "Accept": "application/json",
  },
  body: JSON.stringify({key: updatedValue}),
};


fetch('fetchURL/items/${item.id}', patchConfig);
  .then(response => response.json())
  .then(newItem => handleUpdateItem(newItem))
Enter fullscreen mode Exit fullscreen mode

Delete

Deleting requires us to use the filter array function.
If we simply let everything in except for the deleted item, we achieve our goal again without deleting from the array in state directly.

const handleDelete = (id) => {
  const updateItemList = itemList.filter((item) => item.id !== id);
  setItemList(updateItemList);
}

fetch(`fetchURL/items/${item.id}`, {
  method: 'DELETE'
 }).then(response => {
    if (response.ok) {
        handleDelete(item.id)
    } else {
        handleError({error: "Item was not deleted"})
    }
})
Enter fullscreen mode Exit fullscreen mode

Conclusion

In the examples above we can see simple methods for applying state, using controlled forms, and fetching in React.
Applying the right method to manipulate the data in state, is imperative.
Now go ahead and try these out, and don't forget to be CRUD-y.

Top comments (0)