DEV Community

Cover image for React fetch example - GET/POST/PUT/DELETE with API
collegewap
collegewap

Posted on • Originally published at codingdeft.com

47

React fetch example - GET/POST/PUT/DELETE with API

In this article, we will see how to make an API call to fetch data in react, update the data, create a new record and delete records.

Project setup

First, create a new react app using the following command:



npx create-react-app react-fetch-get-post-put-delete


Enter fullscreen mode Exit fullscreen mode

Now install BlueprintJS for styling the app.



npm i @blueprintjs/core


Enter fullscreen mode Exit fullscreen mode

Add the following styles in index.css:



@import "~normalize.css";
@import "~@blueprintjs/core/lib/css/blueprint.css";
@import "~@blueprintjs/icons/lib/css/blueprint-icons.css";

body {
  display: flex;
  justify-content: center;
}


Enter fullscreen mode Exit fullscreen mode

Here we are including the blueprint styles we installed earlier.

GET: Displaying user data

We will use JSON placeholder for the APIs.



import { Button, EditableText } from "@blueprintjs/core"
import { useEffect, useState } from "react"
import "./App.css"

function App() {
  const [users, setUsers] = useState([])

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users")
      .then(response => response.json())
      .then(json => setUsers(json))
  }, [])

  return (
    <div className="App">
      <table class="bp4-html-table .modifier">
        <thead>
          <tr>
            <th>Id</th>
            <th>Name</th>
            <th>Email</th>
            <th>Website</th>
            <th>Action</th>
          </tr>
        </thead>
        <tbody>
          {users.map(user => (
            <tr key={user.id}>
              <td>{user.id}</td>
              <td>{user.name}</td>
              <td>
                <EditableText value={user.email} />
              </td>
              <td>
                <EditableText value={user.website} />
              </td>
              <td>
                <Button intent="primary">Update</Button>
                &nbsp;
                <Button intent="danger">Delete</Button>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  )
}

export default App


Enter fullscreen mode Exit fullscreen mode

In the above code,

  • We are fetching the list of users inside the useEffect.
  • Displaying id, name, email, and website of each user.
  • Have 2 action buttons for updating and deleting the user details.

If you run the app now, you will be able to see the list of users:

user data displayed in a table

POST: Adding new user



import "./App.css"
import { useEffect, useState } from "react"
import {
  Button,
  EditableText,
  InputGroup,
  Toaster,
  Position,
} from "@blueprintjs/core"

const AppToaster = Toaster.create({
  position: Position.TOP,
})

function App() {
  const [users, setUsers] = useState([])
  const [newName, setNewName] = useState("")
  const [newEmail, setNewEmail] = useState("")
  const [newWebsite, setNewWebsite] = useState("")

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users")
      .then(response => response.json())
      .then(json => setUsers(json))
  }, [])

  const addUser = () => {
    const name = newName.trim()
    const email = newEmail.trim()
    const website = newWebsite.trim()
    if (name && email && website) {
      fetch("https://jsonplaceholder.typicode.com/users", {
        method: "POST",
        body: JSON.stringify({
          name,
          email,
          website,
        }),
        headers: {
          "Content-type": "application/json; charset=UTF-8",
        },
      })
        .then(response => response.json())
        .then(data => {
          setUsers([...users, data])
          setNewName("")
          setNewEmail("")
          setNewWebsite("")
          AppToaster.show({
            message: "User added successfully",
            intent: "success",
            timeout: 3000,
          })
        })
    }
  }

  return (
    <div className="App">
      <table class="bp4-html-table .modifier">
        <thead>
          <tr>
            <th>Id</th>
            <th>Name</th>
            <th>Email</th>
            <th>Website</th>
            <th>Action</th>
          </tr>
        </thead>
        <tbody>
          {users.map(user => (
            <tr key={user.id}>
              <td>{user.id}</td>
              <td>{user.name}</td>
              <td>
                <EditableText value={user.email} />
              </td>
              <td>
                <EditableText value={user.website} />
              </td>
              <td>
                <Button intent="primary">Update</Button>
                &nbsp;
                <Button intent="danger">Delete</Button>
              </td>
            </tr>
          ))}
        </tbody>
        <tfoot>
          <tr>
            <td></td>
            <td>
              <InputGroup
                value={newName}
                onChange={e => setNewName(e.target.value)}
                placeholder="Add name here..."
              />
            </td>
            <td>
              <InputGroup
                placeholder="Add email here..."
                value={newEmail}
                onChange={e => setNewEmail(e.target.value)}
              />
            </td>
            <td>
              <InputGroup
                placeholder="Add website here..."
                value={newWebsite}
                onChange={e => setNewWebsite(e.target.value)}
              />
            </td>
            <td>
              <Button intent="success" onClick={addUser}>
                Add user
              </Button>
            </td>
          </tr>
        </tfoot>
      </table>
    </div>
  )
}

export default App


Enter fullscreen mode Exit fullscreen mode

In the above code,

  • We have introduced 3 new local states to store name, email, and website.
  • We have added input fields to read name, email, and website.
  • We have a button with the label 'Add user', when clicked will call the addUser function.
  • The addUser function will check if all the values are present, and will call the add user API, which uses the HTTP POST method.
  • Once the user is added successfully, we append the user to the existing users and display a success message.

If you run the application now, you should be able to add a new user.

PUT: Updating user data

We will use the HTTP PUT method to update the data:



import "./App.css"
import { useEffect, useState } from "react"
import {
  Button,
  EditableText,
  InputGroup,
  Toaster,
  Position,
} from "@blueprintjs/core"

const AppToaster = Toaster.create({
  position: Position.TOP,
})

function App() {
  const [users, setUsers] = useState([])
  const [newName, setNewName] = useState("")
  const [newEmail, setNewEmail] = useState("")
  const [newWebsite, setNewWebsite] = useState("")

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users")
      .then(response => response.json())
      .then(json => setUsers(json))
  }, [])

  const addUser = () => {
    const name = newName.trim()
    const email = newEmail.trim()
    const website = newWebsite.trim()
    if (name && email && website) {
      fetch("https://jsonplaceholder.typicode.com/users", {
        method: "POST",
        body: JSON.stringify({
          name,
          email,
          website,
        }),
        headers: {
          "Content-type": "application/json; charset=UTF-8",
        },
      })
        .then(response => response.json())
        .then(data => {
          setUsers([...users, data])
          setNewName("")
          setNewEmail("")
          setNewWebsite("")
          AppToaster.show({
            message: "User added successfully",
            intent: "success",
            timeout: 3000,
          })
        })
    }
  }

  const updateUser = id => {
    const user = users.find(user => user.id === id)

    fetch(`https://jsonplaceholder.typicode.com/users/${id}`, {
      method: "PUT",
      body: JSON.stringify(user),
      headers: {
        "Content-type": "application/json; charset=UTF-8",
      },
    })
      .then(response => response.json())
      .then(() => {
        AppToaster.show({
          message: "User updated successfully",
          intent: "success",
          timeout: 3000,
        })
      })
  }

  const onChangeHandler = (id, key, value) => {
    setUsers(values => {
      return values.map(item =>
        item.id === id ? { ...item, [key]: value } : item
      )
    })
  }

  return (
    <div className="App">
      <table class="bp4-html-table .modifier">
        <thead>
          <tr>
            <th>Id</th>
            <th>Name</th>
            <th>Email</th>
            <th>Website</th>
            <th>Action</th>
          </tr>
        </thead>
        <tbody>
          {users.map(user => (
            <tr key={user.id}>
              <td>{user.id}</td>
              <td>{user.name}</td>
              <td>
                <EditableText
                  value={user.email}
                  onChange={value => onChangeHandler(user.id, "email", value)}
                />
              </td>
              <td>
                <EditableText
                  value={user.website}
                  onChange={value => onChangeHandler(user.id, "website", value)}
                />
              </td>
              <td>
                <Button intent="primary" onClick={() => updateUser(user.id)}>
                  Update
                </Button>
                &nbsp;
                <Button intent="danger">Delete</Button>
              </td>
            </tr>
          ))}
        </tbody>
        <tfoot>
          <tr>
            <td></td>
            <td>
              <InputGroup
                value={newName}
                onChange={e => setNewName(e.target.value)}
                placeholder="Add name here..."
              />
            </td>
            <td>
              <InputGroup
                placeholder="Add email here..."
                value={newEmail}
                onChange={e => setNewEmail(e.target.value)}
              />
            </td>
            <td>
              <InputGroup
                placeholder="Add website here..."
                value={newWebsite}
                onChange={e => setNewWebsite(e.target.value)}
              />
            </td>
            <td>
              <Button intent="success" onClick={addUser}>
                Add user
              </Button>
            </td>
          </tr>
        </tfoot>
      </table>
    </div>
  )
}

export default App


Enter fullscreen mode Exit fullscreen mode

In the above code,

  • We have a function onChangeHandler, which will be called whenever the email and website are edited.
  • When the user clicks on the update button we are calling the updateUser function and passing the user id to it.
  • In the updateUser method, we are filtering the user based on the id passed and calling the API with the PUT method to update the user data to API.
  • On successful update, we are displaying a success message.

JSONPlaceholder will not actually update or delete the data. It will just respond as if they are done.

DELETE: Deleting user

We will use the HTTP DELETE method to delete a user record.



import "./App.css"
import { useEffect, useState } from "react"
import {
  Button,
  EditableText,
  InputGroup,
  Toaster,
  Position,
} from "@blueprintjs/core"

const AppToaster = Toaster.create({
  position: Position.TOP,
})

function App() {
  const [users, setUsers] = useState([])
  const [newName, setNewName] = useState("")
  const [newEmail, setNewEmail] = useState("")
  const [newWebsite, setNewWebsite] = useState("")

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users")
      .then(response => response.json())
      .then(json => setUsers(json))
  }, [])

  const addUser = () => {
    const name = newName.trim()
    const email = newEmail.trim()
    const website = newWebsite.trim()
    if (name && email && website) {
      fetch("https://jsonplaceholder.typicode.com/users", {
        method: "POST",
        body: JSON.stringify({
          name,
          email,
          website,
        }),
        headers: {
          "Content-type": "application/json; charset=UTF-8",
        },
      })
        .then(response => response.json())
        .then(data => {
          setUsers([...users, data])
          setNewName("")
          setNewEmail("")
          setNewWebsite("")
          AppToaster.show({
            message: "User added successfully",
            intent: "success",
            timeout: 3000,
          })
        })
    }
  }

  const updateUser = id => {
    const user = users.find(user => user.id === id)

    fetch(`https://jsonplaceholder.typicode.com/users/${id}`, {
      method: "PUT",
      body: JSON.stringify(user),
      headers: {
        "Content-type": "application/json; charset=UTF-8",
      },
    })
      .then(response => response.json())
      .then(() => {
        AppToaster.show({
          message: "User updated successfully",
          intent: "success",
          timeout: 3000,
        })
      })
  }

  const deleteUser = id => {
    fetch(`https://jsonplaceholder.typicode.com/posts/${id}`, {
      method: "DELETE",
    })
      .then(response => response.json())
      .then(() => {
        setUsers(values => {
          return values.filter(item => item.id !== id)
        })
        AppToaster.show({
          message: "User deleted successfully",
          intent: "success",
          timeout: 3000,
        })
      })
  }

  const onChangeHandler = (id, key, value) => {
    setUsers(values => {
      return values.map(item =>
        item.id === id ? { ...item, [key]: value } : item
      )
    })
  }

  return (
    <div className="App">
      <table class="bp4-html-table .modifier">
        <thead>
          <tr>
            <th>Id</th>
            <th>Name</th>
            <th>Email</th>
            <th>Website</th>
            <th>Action</th>
          </tr>
        </thead>
        <tbody>
          {users.map(user => (
            <tr key={user.id}>
              <td>{user.id}</td>
              <td>{user.name}</td>
              <td>
                <EditableText
                  value={user.email}
                  onChange={value => onChangeHandler(user.id, "email", value)}
                />
              </td>
              <td>
                <EditableText
                  value={user.website}
                  onChange={value => onChangeHandler(user.id, "website", value)}
                />
              </td>
              <td>
                <Button intent="primary" onClick={() => updateUser(user.id)}>
                  Update
                </Button>
                &nbsp;
                <Button intent="danger" onClick={() => deleteUser(user.id)}>
                  Delete
                </Button>
              </td>
            </tr>
          ))}
        </tbody>
        <tfoot>
          <tr>
            <td></td>
            <td>
              <InputGroup
                value={newName}
                onChange={e => setNewName(e.target.value)}
                placeholder="Add name here..."
              />
            </td>
            <td>
              <InputGroup
                placeholder="Add email here..."
                value={newEmail}
                onChange={e => setNewEmail(e.target.value)}
              />
            </td>
            <td>
              <InputGroup
                placeholder="Add website here..."
                value={newWebsite}
                onChange={e => setNewWebsite(e.target.value)}
              />
            </td>
            <td>
              <Button intent="success" onClick={addUser}>
                Add user
              </Button>
            </td>
          </tr>
        </tfoot>
      </table>
    </div>
  )
}

export default App


Enter fullscreen mode Exit fullscreen mode

In the code above,

  • We have added the deleteUser function, which will be called when the user clicks on the Delete button.
  • The deleteUser function will receive the id of the user to be deleted and will call the API with the HTTP DELETE method.
  • Once the user is deleted, it will remove the particular user from the users state and display a success message.

Source code and Demo

You can view the complete source code here and a demo here.

API Trace View

Struggling with slow API calls?

Dan Mindru walks through how he used Sentry's new Trace View feature to shave off 22.3 seconds from an API call.

Get a practical walkthrough of how to identify bottlenecks, split tasks into multiple parallel tasks, identify slow AI model calls, and more.

Read more →

Top comments (0)

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay