useEffect Simplified

useEffect Simplified

let's perform some side-effects...

Summary:

  • let you perform side effects in the functional components.

  • it is a close replacement for componentDidMount, componentDidUpdate & componentWillUnmount from classes.

Syntax:

useEffect(() => {

  },[])

Basic Example of useEffect:

  • Here we are displaying the current count on the website’s title using useEffect.

  • With this useEffect, we are asking React to run the argument mentioned inside the useEffect whenever the component re-renders.

  • In short, it will run after the initial render and then update after every subsequent re-render, just like componentDidMount and componentDidUpdate in classes.

function UseEffectExample() {
  const initialCount = 0
  const [count, setCount] = useState(initialCount)

  useEffect(() => {
    document.title = `you click ${count} times`
  })
  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={() => setCount((prevCount) => prevCount + 1)}>
        Increment Count
      </button>
    </div>
  )
}

Conditionally running side effect

  • We know that running the side-effect after every render can cause performance issues, so there is a way to conditionally run useEffect.

  • If we extend the above example and add another useState to save the name whenever the user enters it in the input form, we will find that useEffect is still getting triggered, which is a big performance issue.

function ConditionaluseEffect() {
  const [count, setCount] = useState(0)
  const [name, setName] = useState("")

  useEffect(() => {
    document.title = `you click ${count} times`
    console.log("Updating Document Title")
  }, [count])
  return (
    <div>
      <input
        type="text"
        value={name}
        onChange={(e) => setName(e.target.value)}
      />
      <button onClick={() => setCount((prevCount) => prevCount + 1)}>
        Click {count} times
      </button>
    </div>
  )
}

Rendering it once!

  • if you want to render the useEffect only once then you can add a empty array dependency at the back.

  • below is the example where we are going to call useEffect only once and it will be called on any re-render when the mouse will move.

function LoggingMouseMovement() {
  const [x, setX] = useState(0)
  const [y, setY] = useState(0)

  const logMousePosition = (e) => {
    console.log("mouse event")
    setX(e.clientX)
    setY(e.clientY)
  }

  useEffect(() => {
    console.log("useEffect Called")
    window.addEventListener("mousemove", logMousePosition)
  }, [])

  return (
    <div>
      Hooks X - {x} & Y - {y}
    </div>
  )
}

useEffect with cleanup

  • We have componentDidUnmount in classes, but for useEffect we return a clean-up function, like we have done in the code below.
function MouseCord() {
  const [x, setX] = useState(0)
  const [y, setY] = useState(0)

  const logMousePosition = (e) => {
    console.log("mouse event")
    setX(e.clientX)
    setY(e.clientY)
  }

  useEffect(() => {
    console.log("useEffect Called")
    window.addEventListener("mousemove", logMousePosition)

    // Code Cleanup Here!
    return () => {
      console.log("Component Cleanup Code")
      window.removeEventListener("mousemove", logMousePosition)
    }
  }, [])

  return (
    <div>
      Hooks X - {x} & Y - {y}
    </div>
  )
}

function MouseContainer() {
  const [display, setDisplay] = useState(true)
  return (
    <div>
      <button onClick={() => setDisplay(!display)}>Toggle Display</button>
      {display ? <MouseCord /> : null}
    </div>
  )
}
  • We are creating a button to display or hide the logMousePosition function, but when hiding the function, useEffect is still running the addEventListener, as we can see in the console.

  • Now see the code after adding the clean-up function in which we are removing the event listener.

Fetching Data using useEffect

  • In this, we are fetching the post when the user types a number in the input field and then clicks the button.

  • So, here useEffect will only get triggered when you click on the button. hence saving the unnecessary API calls.

function DataFetching() {
  const [post, setPost] = useState({})
  const [id, setId] = useState(1)
  const [idFromButtonClick, setIdFromButtonClick] = useState(1)

  const handleClick = () => {
    setIdFromButtonClick(id)
  }

  useEffect(() => {
    axios
      .get(`https://jsonplaceholder.typicode.com/posts/${idFromButtonClick}`)
      .then((res) => {
        console.log(res, "res")
        setPost(res.data)
      })
      .catch((err) => {
        console.log(err)
      })
  }, [idFromButtonClick])

  return (
    <div>
      <input type="text" value={id} onChange={(e) => setId(e.target.value)} />
      <button type="button" onClick={handleClick}>
        Get Post
      </button>
      <div>{post.title}</div>
    </div>
  )
}

and that’s useEffect, can be overwhelming at first but constant practice of useEffect will definitely help you in becoming a good react developer. Thanks a lot for making it to the end.

Did you find this article valuable?

Support Ansub Khan by becoming a sponsor. Any amount is appreciated!