You probably haven't understood react useEffect yet.
making sense of the useEffect hook and understanding its purpose.
Table of contents
- What is useEffect for?
- What not to do with useEffect
- Setting derived state: One of the most common mistakes made with the useEffect hook is to use it for listening to changes on some props in order to update some other variables accordingly. this is an inefficient way of using the hook. a better alternative would be to eliminate the useEffect hook altogether and just set the variable directly as a standard pure variable in the component's scope. the variable will always be recalculated whenever any of its constituent state variables changes. for example below is a bad followed by a good practice when setting derived states.
- Setting any state: it might be tempting at times to do some activities in the useEffect that mutates the state of the app. this is actually a very dangerous practice and can easily lead to an infinite loop of rerenders. this also is one of the reasons why it is advised to use a framework for data fetching. fetching data yourself with useEffect will get data that will at some point be stored in state and if not well managed can easily cause rerenders in a loop.
- Sunning event handles: even though it is called the useEffect hook, it is not really suitable for effects caused by events, the best way to handle your events is in the event handlers close to the state changes, rather than listening to changes in useEffect to run effects.
- component initialized Variables: You should be careful about using objects declared in the same component as the useEffect, these Objects should not be put in the dependencies array as this will cause the useEffect to run every time the component is rendered due to the fact that for each render, a new and different instance of the object is created.
- Conclusion
Hey there! this article is a follow-up to one of my articles where I describe why the useEffect hook renders twice and how to stop it possibly.
The useEffect hook is a very used and thus popular hook in the react's ecosystem, it serves its purpose when used correctly but can represent a 'foot gun' when used incorrectly and so resulting in a lot of hate from some devs. Actually, the useEffect hook is less of a dangerous hook or tool, and more of a misunderstood one. In order to fully enjoy the potential of this hook, one must understand the initial purpose for which the hook was designed and published.
What is useEffect for?
- The useEffect hook can be seen as an "escape hatch" as described by the React Docs Beta, this means that the useEffect serves as a portal through which you can synchronize your app's states with external systems, these could be a subscription to a server's services, a non-react widget, or other external services.
let's look at an example here. let's say we have an app that makes a connection with a server for a particular component, the connection might need some arguments like some id from the react component, and should always be in sync with these arguments. in order to create this connection and keep it in sync with our app's states, the useEffect hook would be suitable
const server = new Server()
export default function app({id}){
useEffect(()=>{
server.connect(id)
return ()=> server.disconnect()
},[id])
}
notice how I added the id prop to the dependency array so that the connection will always be remade when the id changes and thus always be In sync with the latest Id. Also, notice how I added a clean-up function to maintain consistency and avoid bugs caused by multiple unnecessary connection instances.
You could also use useEffect to fetch data from the server for use in your application, but it is mostly advised to use a framework for that task because while it is possible, the odds of you falling into issues like "race conditions", "untrue dependency array", and other issues are high. some frameworks that might serve the purpose here are,
-react query
-remix
-useSWR()
-and the use() function which is relatively new and cool.
What not to do with useEffect
Hopefully, you now understand that the useEffect hook is more for synchronizing than performing effects in our apps. therefore if you are having useEffects all over the place in your code then you are probably using it wrong. Here are some instances where you might be using the useEffect wrongly.
Setting derived state: One of the most common mistakes made with the useEffect hook is to use it for listening to changes on some props in order to update some other variables accordingly. this is an inefficient way of using the hook. a better alternative would be to eliminate the useEffect hook altogether and just set the variable directly as a standard pure variable in the component's scope. the variable will always be recalculated whenever any of its constituent state variables changes. for example below is a bad followed by a good practice when setting derived states.
// bad practice
export default function app(){
const [ state , setState ] = useState()
const [ derived , setDerived ] = useState()
useEffect(()=>{
setDerived(state + 1)
},[state])
// app statements continue...
}
// better
export default function app(){
const [ state , setState ] = useState()
const derived = state + 1
// app statements continue...
}
Setting any state: it might be tempting at times to do some activities in the useEffect that mutates the state of the app. this is actually a very dangerous practice and can easily lead to an infinite loop of rerenders. this also is one of the reasons why it is advised to use a framework for data fetching. fetching data yourself with useEffect will get data that will at some point be stored in state and if not well managed can easily cause rerenders in a loop.
Sunning event handles: even though it is called the useEffect hook, it is not really suitable for effects caused by events, the best way to handle your events is in the event handlers close to the state changes, rather than listening to changes in useEffect to run effects.
component initialized Variables: You should be careful about using objects declared in the same component as the useEffect, these Objects should not be put in the dependencies array as this will cause the useEffect to run every time the component is rendered due to the fact that for each render, a new and different instance of the object is created.
Conclusion
In conclusion to this article, the useEffect hook is a very useful tool that just needs to be understood and used for its purpose. when used correctly, it offers so much value.
so guys those are some insights on the useEffect hook, to continue learning I would advise you to go to the new react docs React Docs Beta, and till next time, happy coding.