Search code examples
javascriptreactjsreact-hooksuse-effect

What is the point of useEffect() if you don't specify a dependancy


I am using react hooks in a functional component, and was wondering what the use of useEffect is when you don't specify a dependency. I know the docs state it is used for side effects, but my question is why can't these side effects just be run with plain JS inside the functional component? As a very basic example I was playing with the following code:

import {useEffect, useState} from 'react'

function Child () {

  const [clickCount, updateCount] = useState(0)

  console.log('Run outside of useEffect')

  useEffect(()=>{
    console.log("Run inside of useEffect")
  })


  return (

    <button onClick = {() => updateCount(clickCount+1)}> Child COmponent </button>
  )
}

export default Child

As you would expect given it is basically just a normal JS function, on every re-render caused by a button click, both console.log's are executed.

I understand why you may want to use useEffect in a situation such as below, where you only want to run useEffect if something specific changes:

import {useEffect, useState} from 'react'

function Child () {

  const [clickCount, updateCount] = useState(0)

  console.log('Run outside of useEffect')

  //this now only runs when `someVariable` changes
  useEffect(()=>{
    
    console.log("Run inside of useEffect")
  }, [someVariable])


  return (

    <button onClick = {() => updateCount(clickCount+1)}> Child COmponent </button>
  )
}

export default Child

But this begs the question, what is the point of using useEffect unless you specify the dependency matrix as a second argument? Can't side effects just be run normally using plain JS?


Solution

  • what is the point of using useEffect unless you specify the dependency matrix as a second argument?

    Specifying the dependency array is an optimization to tell React to skip executing the effect if certain values haven't changed between different renders of a component.

    Can't side effects just be run normally using plain JS?

    Effects that are executed at the top-level inside functional component execute in a different way as compared to the effect inside the useEffect hook.

    When effects are inside the useEffect:

    • They are executed after browser has painted the screen, i.e. after React has applied changes to the DOM.
    • Before running the effect again, useEffect can run the clean-up function, if clean-up function is provided.
    • Specifying the dependency array will allow you to skip running the effect after every re-render of the component.
    • Omitting the array may cause an infinite re-render.

    Because of the above mentioned points, you always want the side-effects to be executed inside the useEffect hook.

    As far as the effects at the top-level code in the functional component are concerned, consider the following points:

    • Will execute the effect before user sees anything on the screen, i.e. effect will execute before React updates the DOM.

    • You will have no clean-up mechanism that could be executed before running the effect again.