Unveiling CRUD Operations in React with fetch API 🚀

🚀 As developers, we embark on an exciting journey through the vibrant landscape of operations integral to modern software development—operations that encapsulate the fundamental aspects of Create, Read, Update, and Delete. Familiarly known as CRUD operations, these cornerstones form the bedrock of interaction with data in applications. While the concept is straightforward, a deeper exploration adds a touch of intrigue to the mix! 🧐

But worry not, we're about to unravel the magic! ✨✨

Before we dive into the enchanting world of performing CRUD operations within a React application using the fetch API, let's embark on a quick overview of these vital operations. The "C" stands for "Create," and it's our ticket to bringing new data to life through the POST method. It's like creating a masterpiece out of thin air! 🖌️ Moving forward, "R" denotes "Read," executed via the GET method, and it's like opening up the treasure chest of data from the database. 📚 Transitioning to "U," symbolizing "Update," we wield the powerful spells of the PUT and PATCH methods. These two conjure changes to the data, with a slight syntax twist setting them apart. 🪄 Lastly, the "D" signifies "Delete," a noble quest accomplished with the DELETE method—it's like vanquishing the data dragons from the realm. 🗡️

With our spellbook of knowledge at hand, it's time to weave these enchantments into a React application. But fret not, our adventure is accompanied by a simulated API—a friendly guide to understanding the concepts without getting lost in the woods. 🌳 So grab your virtual wands, for the upcoming sections will unravel the intricacies of each operation, weaving the threads that form the tapestry of modern web development. 🌐✨

🔽 Using 'GET' Request for Effortless Data Retrieval (Read)

  • The 'GET' request is fundamental for retrieving data from a remote server in React applications.

  • It's a core component of the Read aspect in CRUD operations.

  • Through a 'GET' request, we fetch data from the server without making any changes.

  • This method seamlessly updates our application with real-time data.

  • The 'GET' request is aligned with React's emphasis on dynamic user experiences.

  • By utilizing a 'GET' request, we bridge the gap between frontend and backend, ensuring efficient data flow.

  • Implementing a 'GET' request involves utilizing the fetch API to send requests to server endpoints.

  • Upon receiving a 'GET' request, the server responds with the requested data in the response body.

  • In React, we handle the asynchronous nature of the 'GET' request using async/await.

  • Let's delve into the code and grasp the effective integration of 'GET' requests into our React application. 🚀🔍

NOTE: By default fetch api uses `get` method !!

import React, { useEffect, useState } from "react";

const API = "https://jsonplaceholder.typicode.com/posts";

function ApiGET() {
    // State to hold the fetched posts
    const [posts, setPosts] = useState([]);

    // Function to fetch data from the API and update state
    const fetchPosts = async () => {
        try {
            const response = await fetch(API);
            const data = await response.json();
            setPosts(data); // Store the fetched data
            console.log(data);
        } catch (error) {
            console.error("Error fetching data:", error);
        }
    };

    // Call fetchPosts inside the useEffect() hook
    useEffect(() => {
        fetchPosts();
    }, []);

    return (
        <>
            <h1>Using 'GET' Method</h1>
            {/* Rendering the fetched data */}
            <ul>
                {posts.map((post) => (
                    <li key={post.id}>{post.title}</li>
                ))}
            </ul>
        </>
    );
}

export default ApiGET;

Result of the get method.

📮 Creating and Adding Data with the 'POST' Method.

Welcome to a compelling exploration of the 'POST' method—an essential aspect of data manipulation in web development. In this discussion, we'll dissect a complex yet illustrative example that leverages form validation using the esteemed 'yup' library and the versatile useForm hook.

Decoding the Purpose of 'POST'

In the realm of HTTP methods, the 'POST' method stands tall as a crucial instrument for transmitting data to servers. It's particularly prominent when collecting user input through forms, creating an avenue for dynamic data submission. In this exposition, we delve into the intricacies of 'POST,' unveiling its mechanics within a formal context.

An Example of Complexity and Insight

  • Prepare for a detailed exposition that navigates beyond the ordinary. Our journey involves form validation intricately interwoven with the 'POST' method. This intricate interplay is achieved through the adept utilization of the 'yup' validation library and the 'useForm' hook—a demonstration of how robust data transmission seamlessly aligns with validation best practices.

  • While familiarity with form validation might enhance comprehension, rest assured that prior knowledge is not a prerequisite. We endeavor to elucidate the 'POST' method's mechanics, providing a clear and informative walkthrough. Whether you're a seasoned practitioner or new to the realm of data submission, this exploration offers an insightful perspective.

  • With meticulous attention to detail, we invite you to embark on this exploration of the 'POST' method's role in data exchange. Together, we'll uncover the layers that constitute effective data submission and gain an understanding of the techniques that underscore successful interaction with remote servers. 🚀

NOTE : In contrast to 'GET,' crafting a 'POST' request requires explicit specification of key components:

1. Method: While 'GET' is implied, 'POST' necessitates explicit mention of the method. This is often set to "POST" in the request.

2. Headers: Headers provide essential metadata about the request. For 'POST' requests, the "Content-Type" header typically includes the value "application/json" to indicate the content format.

3. Request Body: Unlike 'GET,' where data is sent in the URL, 'POST' requests embed data in the request body. This is usually formatted as a JSON object, encapsulating the data to be transmitted.

import React from "react";
import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";

const API = "https://jsonplaceholder.typicode.com/todos";

function ApiPOST() {
    // Define validation schema using Yup
    const schema = yup.object().shape({
        fullName: yup.string().required("Your full name is required"),
        email: yup.string().email().required(),
        age: yup.number().positive().integer().min(18).required(),
        password: yup.string().min(6).max(20).required(),
        confirmPassword: yup
            .string()
            .oneOf([yup.ref("password"), null], "Passwords don't match")
            .required(),
    });

    // Initialize react-hook-form
    const {
        register,
        handleSubmit,
        formState: { errors },
    } = useForm({ resolver: yupResolver(schema) });

    ////////////////////////////////////////////////////////////////////////////
    // PART WHERE YOU NEED TO FOCUS: 👇
    // Define the onSubmit function to handle the form submission
    const onSubmit = async (data) => {
        try {
            const response = await fetch(API, {
                method: "POST",
                headers: { "content-type": "application/json" },
                body: JSON.stringify(data),
            });

            if (response.ok) {
                const responseData = await response.json();
                console.log("Response Data : ", responseData);
            } else {
                console.error("POST request failed with status:", response.status);
            }
        } catch (error) {
            console.error("Error sending POST request:", error);
        }
    };
    //////////////////////////////////////////////////////////////////////////

    return (
        <form
            onSubmit={handleSubmit(onSubmit)}
            style={{ display: "flex", flexDirection: "column", gap: "1rem" }}
        >
            <input type="text" placeholder="Full Name" {...register("fullName")} />
            <p style={{ color: "red" }}>{errors.fullName?.message}</p>
            <input type="email" placeholder="Email" {...register("email")} />
            <p style={{ color: "red" }}>{errors.email?.message}</p>
            <input type="number" placeholder="Age" {...register("age")} />
            <p style={{ color: "red" }}>{errors.age?.message}</p>
            <input type="password" placeholder="Password" {...register("password")} />
            <p style={{ color: "red" }}>{errors.password?.message}</p>
            <input
                type="password"
                placeholder="Confirm Password"
                {...register("confirmPassword")}
            />
            <p style={{ color: "red" }}>{errors.confirmPassword?.message}</p>
            <input type="submit" />
        </form>
    );
}

export default ApiPOST;

RESPNOSE OBTAINED FROM POST METHOD

"So, my fellow explorers, if you've successfully grasped the concepts discussed thus far, I applaud your progress. You're on the brink of mastering these foundational aspects. Excitingly, the upcoming methods—PUT, PATCH, and DELETE—won't stray far from the path we've treaded with the 'POST' method. It's akin to adding finishing touches to a masterpiece you've already begun. As we celebrate your accomplishment, let's seamlessly transition into the exploration of these remaining methods. Your journey of understanding continues with enthusiasm and determination! 🎉🚀"

🛠️ Updating with PUT and PATCH Methods...

When updating with PUT, you provide a full new version of the resource. PATCH is for making partial updates, efficiently modifying specific details without sending the whole resource. Both methods aim for consistency, but PUT swaps the entire resource, while PATCH tweaks parts of it.

PUT Method:

  • Full Update: Replaces the entire resource with new data.

  • Complete Payload: Requires sending the complete updated resource.

  • Idempotent: Multiple identical requests have the same effect as a single request.

Here is the example of how we will be writing a `put` method.

    const onSubmit = async (data) => {
        try {
            const response = await fetch(API, {
                method: "PUT",
                headers: { "content-type": "application/json" },
                body: JSON.stringify(data),
            });

            if (response.ok) {
                const responseData = await response.json();
                console.log("Response Data : ", responseData);
            } else {
                console.error("PUT request failed with status:", response.status);
            }
        } catch (error) {
            console.error("Error sending PUT request:", error);
        }
    };

PATCH Method:

  • Partial Update: Updates specific fields or attributes.

  • Selective Payload: Only includes the changes to be made.

  • Idempotent: Repeated identical requests yield the same result.

Here is the example of how we will be writing a `patch` method.

const onSubmit = async (data) => {
        try {
            const response = await fetch(API, {
                method: "PUT",
                headers: { "content-type": "application/json" },
                body: JSON.stringify(data),
            });

            if (response.ok) {
                const responseData = await response.json();
                console.log("Response Data : ", responseData);
            } else {
                console.error("PUT request failed with status:", response.status);
            }
        } catch (error) {
            console.error("Error sending PUT request:", error);
        }
    };

Delete using `delete` method

DELETE Method:

  • Purpose: The DELETE method is used to remove a resource from a server.

  • Resource Address: You specify the URL of the resource you want to delete.

  • Idempotent: Like other CRUD methods, DELETE is idempotent, meaning multiple identical requests have the same effect as a single request.

  • No Request Body: Unlike POST or PUT, DELETE requests usually don't include a request body, as they solely focus on resource removal.

import React from "react";

const API = "https://jsonplaceholder.typicode.com/todos/4";

function ApiDelete() {
    // Function to handle the delete action
    const deletePost = async () => {
        try {
            // Sending a DELETE request to the API endpoint
            const response = await fetch(API, {
                method: "DELETE",
            });

            // Parsing the response JSON data
            const data = await response.json();

            // Logging the response data
            console.log("Deleted Post Data:", data);
        } catch (error) {
            console.error("Error deleting post:", error);
        }
    };

    return (
        <div>
            <button onClick={deletePost}>Delete Post</button>
        </div>
    );
}

export default ApiDelete;

Conclusion

"Congratulations, amazing readers! 🎉🚀 We've journeyed through the exciting world of CRUD operations using the Fetch API in React. From the foundational 'GET' requests to the dynamic dance of 'POST,' 'PUT,' 'PATCH,' and the decisive 'DELETE,' we've explored the heart of web development.

As we wrap up, a big thank you for joining in! 🙌📚 I trust this post added value to your toolkit and enhanced your grasp of these key operations. If any doubts arise or if something seems off, please don't hesitate to reach out—your insights matter.

Stay ready for more exciting content ahead! 🌟🌐 The adventure continues, uncovering even more web development wonders. Your time is appreciated, and your enthusiasm is infectious. Until we meet again for another coding escapade, happy learning! 💻🌈"