Why I gave up on useEffect ?
Don't use useEffect
for every damn state update!
It'll slow your app down and cause unnecessary re-renders. And if you forget to clean up after yourself or you'll end up with memory leaks that'll ruin your app's performance. Oh, and don't even get me started on using async functions inside useEffect
โ that'll just lead to a mess of unpredictable behavior and race conditions. Stick to async/await
or Promise
and save yourself the headache.
Performance issues
Improper use of useEffect
hook can lead to performance issues. If you have too many useEffect
hooks, it can result in too many unnecessary re-renders of your component, especially if you're not careful with the dependencies array. This can negatively impact the performance of your application.
Unforeseen side effects
If you're not careful, it's possible to cause unintended side effects with useEffect
hooks. If the function passed to useEffect
perform a state update that triggers another useEffect
hook, it can cause a chain reaction that's difficult to debug.
Complexity
The useEffect
hook can make the code more complex, especially when dealing with complex state management. It makes it harder to reason about the state of your application, especially if you have multiple useEffect
hooks with complex dependencies.
Here's an example of how multiple useEffect
hooks with complex state management can make the code more complex. In this example, we have two useEffect hooks that manage state updates and API calls. It can get complex if we need to add more state and more useEffect
hooks to handle it. Care needs to be taken to ensure that the code stays readable and maintainable.
import React, { useState, useEffect } from 'react';
function App() {
const [count, setCount] = useState(0);
const [isLoading, setLoading] = useState(false);
const [data, setData] = useState([]);
useEffect(() => {
setLoading(true);
fetch(`https://jsonplaceholder.typicode.com/posts?userId=${count}`)
.then(res => res.json())
.then(data => {
setData(data);
setLoading(false);
})
.catch(() => setLoading(false));
}, [count]);
useEffect(() => {
const interval = setInterval(() => {
setCount(count => count + 1);
}, 5000);
return () => clearInterval(interval);
}, []);
return (
<div>
{isLoading ? <p>Loading...</p> :
<ul>
{data.map(item => (
<li key={item.id}>{item.title}</li>
))}
</ul>
}
</div>
);
}
Much better SWR
SWR stands for "Stale-While-Revalidate" and is a data-fetching library for React applications. It provides a simple and efficient way to fetch and cache data from APIs, with built-in support for features like pagination, revalidation, mutation, deduping, caching, and error handling. I stopped using useEffect, and feel like everyone building a medium size web app, should too !
Understanding SWR logic
After an API call, it returns a cached value first to make the UI render instantly, while it also revalidates the data (fetches the latest data and compares the difference) and updates the state if there is any change. In that manner, there's a lot of improved performance as we are getting the data quickly from the cache and not calling the API again, and a much quicker and optimistic UI-based response.
If we update any data, we can easily call the mutate
function which will update the cached data.
Super clean code
Here is an example code snippet which btw looks much cleaner than useEffect that shows how to use SWR to fetch data from an API:
import useSWR from 'swr';
function MyComponent() {
const { data, error } = useSWR('https://jsonplaceholder.typicode.com/users');
if (error) return <div>Error loading data</div>; // in-built error checking
if (!data) return <div>Loading...</div>; // in-built loading
return (
<div>
<h1>Users</h1>
<ul>
{data.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}
export default MyComponent;
How is SWR better ?
Simplified code
In contrast to useEffect
and state management, SWR simplifies data fetching code by providing a single hook that handles fetching, caching, and state management. This results in less code overall, making it easier to read, debug, and maintain.
Caching and revalidation
SWR improves React data fetching performance with built-in caching and revalidation for frequently changing or large datasets. It updates cached data automatically and reduces network calls by allowing you to set revalidation frequency. This helps in faster response, but fewer API calls.
Deduplication
If multiple components are trying to fetch the same data at the same time, SWR
will make sure that only one request is sent to the server and subsequent requests are deduplicated. SWR
achieves this by caching the response of the first request and using that response for subsequent requests. If you call the same API 10 times, it'll be called just 1 time.
function Avatar () {
const { data, error } = useUser()
if (error) return <Error />
if (!data) return <Spinner />
return <img src={data.avatar_url} />
}
// useUser()'s API will be called just once.
function App () {
return <>
<Avatar />
<Avatar />
<Avatar />
<Avatar />
<Avatar />
</>
}
Conclusion
SWR is the React library that stands out in simplifying data fetching, elevating performance with caching and revalidation, and eliminating the hassle of redundant requests. It takes complex state management to the next level, surpassing the traditional useEffect hook in terms of efficiency.
DROP A FOLLOW ๐๐๐