React hooks are pretty new thing but already a lot of people use it. There is very good documentation on the page. Still, there is small thing that a lot of us don’t see or don’t know. That can cause some optimization issues witch are hard to recognize at the start. This is not an error or even bad coding, just some small misunderstanding of subject. React useState gives a lot of possibilities to optimize your app – but do this wise with full understanding how it works!

This is really short article but I have a hope that will help you understand this simple issue. Lets check short example.

import React, { useEffect, useState } from 'react'

const DATA_PATH = '/path/to/file/with/data.csv'

export const Component: React.FC = () => {

  const [data, setData] = useState('')
  const [showLoader, setShowLoader] = useState(true)

  const fetchData = async () => {
    try {
      const file = await fetch(DATA_PATH)
      const text = await file.text()
      setData(text)
      setShowLoader(false)
    } catch (error) {
      console.error(error)
    }
  }

  useEffect(() => {
    fetchData()
  }, [])

  return (
    <p>
      {showLoader ? 'Loading data...' : data}
    </p>
  )
}

Right here we are fetching some data. When the component did mount there is a fetch. Then we set the data and loader. Everything seems to be ok, but… But our component will render tree times. One before data fetch, then when we will set the data and third time when we set loader. In case that this is some list component or data set is big we can have some problems with performence of our app. It’s simple, it works but you need to have on your mind that this solution can be source of problems later. Hard to test – you need to add test how many times this component renders. At list it’s not to hard to check this issue with React Dev Tools.

What we can do to optimize this component from three renders to two?

Remember: setState will change the state so component will re-render! But state is an object – it can contain more values!

Lets change a little bit example from above. React useState can be done this way:

import React, { useEffect, useState } from 'react'

const DATA_PATH = '/path/to/file/with/data.csv'

export const Component: React.FC = () => {

  const [state, setState] = useState({
    data: '',
    loader: true,
  })

  const fetchData = async () => {
    try {
      const file = await fetch(DATA_PATH)
      const text = await file.text()
      setState({
        data: text,
        loader: false,
      })
    } catch (error) {
      console.error(error)
    }
  }

  useEffect(() => {
    fetchData()
  }, [])

  return (
    <p>
      {state.loader ? 'Loading data...' : state.data}
    </p>
  )
}

This way we have only two renders. In some cases that can be crucial change. Have that on your mind!

Do you want to try React Component TDD – check this out!

If this article was helpful for you – buy me a 🍺🍺🍺


0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *