CRUD and Event Handling in React
Tags: react, beginners, crud
Published: 2022-06-01 02:39:36


### 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

### <u>GET</u>

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))
  }, [])
```

### <u>POST</u>

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;

```

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)
}
```
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.

### <u>PATCH</u>

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))
```

### <u>Delete</u>

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"})
	}
})
```

### 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.