On gists
Fetch userlist with handling via AbortController
•
React
App.jsx
Raw
#
import { useEffect, useState } from "react"
import { User } from "./User"
export default function App() {
const [users, setUsers] = useState([])
const [error, setError] = useState(null)
const [status, setStatus] = useState("idle")
useEffect(() => {
setStatus("loading")
setUsers([])
setError(null)
const controller = new AbortController()
fetch("https://jsonplaceholder.typicode.com/users", {
signal: controller.signal,
})
.then(res => {
if (res.ok) return res.json()
throw new Error(`Status code: ${res.status}`)
})
.then(data => {
setUsers(data)
setStatus("fetched")
setError(null)
})
.catch(err => {
if (err.name === "AbortError") return
setError(err)
setUsers([])
setStatus("error")
})
return () => {
controller.abort()
}
}, [])
return (
<>
<h1>User List</h1>
{status === "loading" && <h2>Loading...</h2>}
{status === "error" && (
<>
<h2>Error fetching users</h2>
<p>{error.message}</p>
</>
)}
{status === "fetched" && (
<ul>
{users.map(user => (
<User key={user.id} name={user.name} />
))}
</ul>
)}
</>
)
}
App2.jsx
Raw
#
// 2 variant try-catch, await
import { useEffect, useState } from "react";
import User from "./User";
export default function App() {
const [users, setUsers] = useState([]);
const [status, setStatus] = useState("idle");
useEffect(() => {
const controller = new AbortController();
(async () => {
try {
setStatus("loading");
setUsers([]);
const res = await fetch("https://jsonplaceholder.typicode.com/users", {
signal: controller.signal,
});
if (res.ok) {
setUsers(await res.json());
setStatus("fetched");
return;
}
throw new Error("Error fetching users");
} catch (e) {
if (e.name === "AbortError") return;
setStatus("error");
setUsers([]);
console.log(e.message);
}
})();
return () => {
controller.abort();
};
}, []);
return (
<>
<h1>Users List</h1>
{status === "loading" && <h2>Loading...</h2>}
{status === "error" && <h2>Error!</h2>}
{status === "fetched" && users.length === 0 && <p>No users found.</p>}
{status === "fetched" && <User users={users} />}
</>
);
}
useFetch.js
Raw
#
import { useState, useEffect } from "react"
export function useFetch(url, options = {}) {
const [data, setData] = useState(null)
const [error, setError] = useState(null)
const [status, setStatus] = useState("idle")
useEffect(() => {
setData(null)
setError(null)
setStatus("loading")
const controller = new AbortController()
fetch(url, { signal: controller.signal, ...options })
.then(res => {
if (res.ok) return res.json()
throw new Error(`Status code: ${res.status}`)
})
.then(data => {
setData(data)
setError(null)
setStatus("fetched")
})
.catch(err => {
if (err.name === "AbortError") return
setData(null)
setError(err)
setStatus("error")
})
return () => {
controller.abort()
}
}, [url, options])
return { data, status, error }
}