DEV Community

loading...

React: useEffect

koralarts profile image Karl Castillo Updated on ・2 min read

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)

pic
Editor guide
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

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