Common UseEffects mistakes that even seniors are making
Hernani Fernandes
Posted on January 4, 2021
Learning useEffect in React leads us to assimilate several new concepts and for that reason we leave out small details that can cause big problems.
Most basic implementation:
import { useEffect } from "react"
const MyComponent = () => {
useEffect(() => {
// do something async
})
return <div> Hi! </div>
}
export { MyComponent }
now only what matters:
useEffect(() => {
// do something async
})
but you could also see like this:
const callbackFunction = () => { }
useEffect(callbackFunction)
What is useEffect
?
It's a function that receives two parameters, at first position a callbackFunction and at second position a dependency array:
const callbackFunction = () => { }
const dependencies = [var1,var2,...] // var1, var2,... comes from outside
useEffect(callbackFunction, dependencies)
This callbackFunction is called:
1 - once after each
render
const callbackFunction = () => { alert("2nd see this") }
useEffect(callbackFunction)
return <div>1st see this</div>
2 - once after first
render
const callbackFunction = () => { alert("2nd see this") }
useEffect(callbackFunction, []) // with an empty array [] works like the previous example
return <div>1st see this</div>
3 - once before that component is remove from the screen
const doSomethingBeforeDestroy = async () => { // unsubscribe }
const callbackFunction = () => {
alert("2nd see this")
return doSomethingBeforeDestroy
}
useEffect(callbackFunction, [])
return <div>1st see this</div>
4 - every time when dependencies variables changes
it values
const [myVar, setMyVar] = useState("one")
const handleClick =()=>{
setMyVar("two")
}
const callbackFunction = () => {
alert("2nd see this but also after the click")
}
useEffect(callbackFunction, [myVar])
return <div click={handleClick}>1st see this and click</div>
Most common mistakes:
Unsubscribe events
In example 3 you must be careful that you should always return an asynchronous function
that never returns a value or change to any state
because this component will be destroyed.
Warning: Can't perform a React state update on an unmounted component.
This useEffect return is usually used to unsubscribe socket events or change the store affecting external components but never the own component.
Unexpected renders
In example 4 you should always (ok, not always, there's one case that I will talk in another post) use primitives as dependencies never reference types such as *Functions, Objects or Arrays. Use only string, boolean, number
.
Don't:
const myObject = { message :"hello" }
useEffect(callbackFunction, [myObject])
Do:
const myObject = { message :"hello" }
useEffect(callbackFunction, [myObject.message])
// or
const myObject = { message :"hello" }
useEffect(callbackFunction, [JSON.stringify(myObject.message)])
//or
const myArray = [1,2,3]
useEffect(callbackFunction, [JSON.stringify(myArray)])
If you use one variable but not include it inside the dependencies like this
const [myVar, setMyVar] = useState("one")
const handleClick =()=>{
setMyVar("two")
}
const callbackFunction = () => {
if (!myVar) setMyVar("new user")
}
useEffect(callbackFunction, []) // using myVar but not adding as a dependency
return <div click={handleClick}>1st see this and click</div>
You will probally see the following error
React Hook useEffect has a missing dependency: 'myVar'.
Either include it or remove the dependency array.
Is sometimes necessary to use functions as dependencies then you should make it through useCallback
that I will explain in my next article or simply ignore the eslint
adding a comment like this:
const callbackFunction = () => {
if (!myVar) setMyVar("new user")
}
useEffect(callbackFunction, [myVar]) // eslint-disable-line react-hooks/exhaustive-deps
// this comment above will ignore the error about the setMyVar function dependency
Posted on January 4, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
October 11, 2024