React Data Fetching Patterns - Part I
Francisldn
Posted on November 16, 2022
In React, data fetching from an external API typically involves a few steps, as below:
- send a fetch request
- await for response
- receive the requested data or error
In this article, we will first discuss how data fetching is traditionally done in React using useState-useEffect
hooks. We will then proceed to discuss other data fetching patterns, utilising Suspense - an API made available in React v18 (no longer experimental), as follows:
Click here to access the Github repo for the code examples discussed below.
How data fetching is traditionally done
In React, we traditionally perform data fetching using useState-useEffect
hooks. Within a React component, a state is created using useState
hook to store data. useEffect
hook is executed as the component first mounts or page first renders. The data fetching logic in the useEffect hook will run and data will be stored as a state.
Let's go through the code:
-
users
state is declared withuseState
, together with loading and error states - Within
useEffect
,getUsers
function will execute on component mounts, and the loading state will set to true while waiting for data to be retrieved - On successful data retrieval, the loading and error states will set to false, and
users
state will contain the retrieved data, ready for UI rendering.
export default function CardList() {
const [users, setUsers] = useState<User[]>([])
const [isLoading, setLoading] = useState(false)
const [isError, setError] = useState(false)
useEffect(() => {
setLoading(true)
getUsers(apiURL)
.then(({results:data}) => {
setUsers(
data.map((user:UserApi) => {
return {
id: user.id.value,
firstName: user.name.first,
lastName: user.name.last,
username: user.login.username,
email: user.email,
}}))
})
.catch(() => setError(true))
.finally(() => setLoading(false))
},[])
return (
<div className="grid sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 justify-center grid-cols-1 mt-8">
{isLoading
? <Loading />
: isError
? <ErrorFallBack />
: users.map((user:User) => (<CardItem key={user.id} user={user}/>))
}
</div>
)
}
Downsides
Prop-drilling
While this data fetching pattern works fine for a local component, if there were multiple components that require access to the same set or a subset of the data, then we will need to pass the props through multiple child components, which could lead to problems of prop-drilling. For a larger app, prop-drilling through multiple layers of components can make the app unwieldy and hard to manage.
To overcome the issues outlined above, let's proceed to look at a few other data fetching methods, as below.
To be continued:
If you like the content, please hit the like button so that it can reach more people.
Posted on November 16, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.