A PATCH Request in React.js

A Step-by-Step Guide to Confidently Updating your Data

A PATCH Request in React.js

Code logic that is repeated over and over again, IMHO, requires a template. A swipe sheet. Something that will prevent people from having to reopen their old applications to copy and paste the steps from before or - even worse - trying to figure it out all over again.

One process you'll see over and over again is this:

  1. Set up the initial render of a collection of data

  2. Allow for the modification of one of the objects in the collection

  3. Update the entire collection's database and state with the modified data

  4. Rerender the entire, modified, collection

When I was learning how to do this, I couldn't find a simple step-by-step for reference and found myself using less than the best code practices, to say the least. While it may be too late for me, it is not too late for you.

In the example below, I will be updating the amount of likes each item has using a button. You can replace that code with however your data is being modified.

Here are your step-by-step instructions:

1: Set up the initial render of a collection of data

// List.js

import { useState, useEffect } from "react"
import Item from "./Item"

function Items() {

//Create a state to hold the collection of data

    const [items, setItems] = useState([])

//Fetch the data and set it to state

    useEffect(()=>{
        fetch("http://localhost:3001/items")
        .then(r => r.json())
        .then(data => setItems(data))
    }, [])

//Map through the data and pass down each object of the array to a child component, for rendering.

    return (
        <>
        {items.map(item=> <Item key={item.id} item={item}/>)}
        </>
    )
}

export default Items;
//Item.js

//Within the child component, render your object's values as needed.
//In this example, we will be interacting with a liker button, 
//updating the value of likes each object has. 

function Item( { item } ) {
    return (
        <>
        <h1>{item.title}</h1>
        <p>{item.body}</p>
        <btn>Likes: {item.likes}</btn>
        </>
    )
}

export default Item;

2: Allow the user to modify the data

//Item.js

//Pass down a callback function from the parent component to the child 
//component as a prop. (We will be creating this function in the next step).

function Item( { item, renderFunction } ) {

//Create an event listener, and call the function that you passed down 
//(which will be responsible for rendering the updated collection),
//within the event listener function. Pass any relevant info, such as the item's
//ID, as arguments.

    function handleClick() {
        callbackFunction(item.id, item.likes)
    }

    return (
        <>
        <h1>{item.title}</h1>
        <p>{item.body}</p>
        <btn onClick={handleClick}>Likes: {item.likes}</btn>
        </>
    )
}

export default Item;

3: Update the database with the modified data

//List.js

import { useState, useEffect } from "react"
import Item from "./Item"

function Items() {

    const [items, setItems] = useState([])

    useEffect(()=>{
        fetch("http://localhost:3001/items")
        .then(r => r.json())
        .then(data => setItems(data))
    }, [])

//Create the function that you passed down to the child component.
//Make a fetch requested, updating the relevant key/s with the new information.

    function callbackFunction(id, likes){

        fetch(`http://localhost:3001/items/${id}`, {
            method: "PATCH",
            headers: {
                "Content-Type": "application/json"
            },
          body: JSON.stringify({
                "likes": likes+1
            })
        })
    }

    return (
        <>
            {items.map(item=> <Item
                key={item.id}
                item={item}
                callbackFunction={callbackFunction}
                />
                )
            }
        </>
    )
}

export default List;

4: Rerender the entire, modified, collection

//List.js

import { useState, useEffect } from "react"
import Item from "./Item"

function Items() {

    const [items, setItems] = useState([])

    useEffect(()=>{
        fetch("http://localhost:3001/items")
        .then(r => r.json())
        .then(data => setItems(data))
    }, [])

//It's time to use the response to update the collection's state.

//In the first ".then", convert the object back to json so it's readable.

//In the second ".then", map through the entire collection and when the 
//item's ID matches the ID of the object you are modifying, return the 
//response object. Otherwise, return the original object.

//Use this new, modified array to update the state of the collection, 
//which will automatically rerender the modification!

    function callbackFunction(id, likes){

        fetch(`http://localhost:3001/items/${id}`, {
            method: "PATCH",
            headers: {
                "Content-Type": "application/json"
            },
          body: JSON.stringify({
                "likes": likes+1
            })
        })
        .then(r => r.json())
        .then((modifiedObj) => {
            const updatedItems = items.map(item=> {
                if (item.id === id) {
                    return modifiedObj;
                } else {
                    return law;
                }
            });
            setItems(updatedItems);
        })
    }

    return (
        <>
            {items.map(item=> <Item
                key={item.id}
                item={item}
                callbackFunction={callbackFunction}
                />
                )
            }
        </>
    )
}

export default List;

And that's that!

The more you do it, the more intuitive it will become.

Good luck!