DEV Community

Karl Castillo
Karl Castillo

Posted on • Updated on

React: useEffect

With functional components more popular than ever with the introduction of hooks, how do we transfer our life cycles from the Class-based component to a functional one?

Please welcome, useEffect. useEffect is React's answer to having some sort of lifecycle in functional components.

useEffect accepts two arguments -- a callback function, and an optional array of dependencies that determines when the effect callback will re-trigger.

useEffect(() => { ... }, [...])
Enter fullscreen mode Exit fullscreen mode

So how does this transfer to the lifecycle of a Class component?

componentDidMount

Every useEffect call will run when the component is considered mounted even if you pass an array of dependencies.

useEffect(callback) // will run on mount
useEffect(callback, []) // will run on mount
useEffect(callback, [item]) // will run on mount
Enter fullscreen mode Exit fullscreen mode

componentWillUnmount

The callback is allowed to return a function that will be triggered whenever the component unmounts or when the effect re-runs again. So it's not a 1-to-1 transfer from componentWillUnmount but it does what it needs to.

useEffect(() => {
  const handleEvent = () => { ... }
  document.addEventListener('resize', handleEvent)

  return () => {
    document.removeEventListener('resize', handleEvent)
  }
})
Enter fullscreen mode Exit fullscreen mode

componentDidUpdate

As said before, the effect can re-run based on if the dependencies passed in the array changes. When there's no array passed, the effect will run every single render.

useEffect(() => {
  console.log('The component re-rendered')
})

useEffect(() => {
  console.log('The value of item changed!')
}, [item])
Enter fullscreen mode Exit fullscreen mode

So how can we use useEffect in a project? One way to use it is to grab data from an api and filter against your local data.

useEffect(() => {
  fetch('https://pokeapi.co/api/v2/pokemon?limit=151')
    .then(res => res.json())
    .then(data => setPokemons(data.results));
}, [])
Enter fullscreen mode Exit fullscreen mode
useEffect(() => {
  // filter Pokemon here
}, [query])
Enter fullscreen mode Exit fullscreen mode

Code Sandbox

Discussion (6)

Collapse
pony profile image
Pony

Thanks for your explanation,
I have a question.

I faced a React Hook call time limit issue.
How many times a React hook can be called in one component?
And How many React Hooks can we use in one component?

Thanks

Collapse
koralarts profile image
Karl Castillo Author

I haven't had the issue of having a limit with React Hooks. I do, however; have seen too many re-render issues. If you have an example, that would help narrow down the question.

As far as I understand, hooks will be called every time your component re-render as they're still regular functions. Whether or not your callback gets called is totally determined by the rules of useEffect.

Collapse
pony profile image
Pony

Oh, Right
Re-render issue, I think
I want to know what is caused by and how to solve this

Thanks in advance.

Thread Thread
koralarts profile image
Karl Castillo Author • Edited on

Let's say you have a useState which returns a setter that we named setValue. If we call setValue outside of any function in our component, it would cause a re-render issue.

const App = () => {
  const [value, setValue] = useState('')
  setValue('value')
  return <p>{value}</p>
}

Another way that would cause this is if two useEffect depend on a value that the other updates.

const [value1, setValue1] = useState('')
const [value2, setValue2] = useState('')
useEffect(() => {
  setValue1('value1')
}, [value2])

useEffect(() => {
  setValue2('value2')
}, [value1])

For more information, you can look at Rules of Hooks

Thread Thread
pony profile image
Pony

Thanks,
It really helps me a great deal.
Appreciate you

Thread Thread
pony profile image
Pony

Thanks, Karl
This really helps me a great deal.
Appreciate your help