Skip to content

Instantly share code, notes, and snippets.

@natafaye
Created July 31, 2022 22:04
Show Gist options
  • Select an option

  • Save natafaye/476671cce2725a17911276763fad6ab3 to your computer and use it in GitHub Desktop.

Select an option

Save natafaye/476671cce2725a17911276763fad6ab3 to your computer and use it in GitHub Desktop.
import React, { useEffect, useState } from 'react'
const fetchAllTasks = async () => {
try {
const response = await fetch("/api/tasks");
// Check if the server successfully responded but the response says something went wrong
if(!response.ok) {
// You could return a nicer error message here instead of just null
return null;
}
const data = await response.json();
return data.tasks;
}
catch (error) {
// Handle issues that happen before we can even get a response (internet issue, backend down)
// You could return a nicer error message here instead of just null
return null;
}
}
const deleteTask = async (id) => {
try {
const response = await fetch("/api/tasks/" + id, { method: "DELETE" })
if(!response.ok) {
return null;
}
return true;
}
catch (error) {
return null;
}
}
export default function App() {
const [taskList, setTaskList] = useState( [] )
// Create some kind of loading piece of state (usually a boolean)
const [loading, setLoading] = useState(false);
// Create some kind of error piece of state (usually a message)
const [errorMessage, setErrorMessage] = useState(null);
const refreshTasks = async () => {
setLoading(true);
const freshTasks = await fetchAllTasks();
if(freshTasks) {
setTaskList(freshTasks);
setErrorMessage(null);
}
else {
setErrorMessage("Failed to fetch")
}
setLoading(false);
}
useEffect(() => {
refreshTasks();
}, [])
const onDeleteClick = async (id) => {
// Set it to true when we start the process
setLoading(true);
const deleteResult = await deleteTask(id);
if(deleteResult) {
setErrorMessage(null);
// Only refresh if delete worked
await refreshTasks();
}
else {
setErrorMessage("Delete failed")
}
// Set it to false when everything is done (make sure to wait)
setLoading(false);
}
return (
<>
<ul>
{ /* Conditionally render the error message */ }
{ errorMessage ? <li className="text-danger list-unstyled">{ errorMessage }</li> : null }
{ /* Conditionally render the loading message */ }
{ loading ? <li className="text-muted list-unstyled">Loading...</li> : null }
{ taskList.map(task => (
<li key={task.id}>
{ task.name }{" "}
{ /* You could use the loading piece of state to disable buttons or change button text */ }
<button disabled={loading} onClick={() => onDeleteClick(task.id)}>{ (loading) ? "Loading..." : "Delete" }</button>
</li>
))}
</ul>
</>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment