Home > Software engineering >  How to refactor with promise in React?
How to refactor with promise in React?

Time:04-23

Visual Studio Code suggests refactoring the code to reduce complexity. I don't know what Promise is and how to refactor the code below. Can anyone help me?

const handleLoadInventory = async () => {
    try {
      const _data = await fetch('http://localhost:4000/api/v1/inventory/', {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
          Authorization: 'Bearer '   localStorage.getItem('token'),
        },
      })

      if (_data.status === 200) {
        const data = await _data.json()

        if (data.items.length !== 0) {
          if (inventoryData.length)
            for (let i = 1; i <= Math.ceil(data.items.length / 10); i  ) {
              pagination.push(i)
            }

          for (let i = 0; i < 10 && i < data.items.length; i  ) {
            showData.push(data.items[i])
          }

          setInventoryData(data.items)
        } else {
          setZeroAlert(true)
        }
      } else {
        setServerAlert(true)
        throw new Error()
      }
    } catch (err) {
      setServerAlert(true)
      console.error(err)
    }
  }

CodePudding user response:

Refactoring is the art of breaking functions down into smaller units. The key idea behind it is to make a function "obvious" by making them small so that mistakes also become obvious. You don't really need to know anything more than how functions work.

The first part I'd extract is the fetch because you'll probably be using it more than once. Copy/pasting the fetch code you have is bug-prone. You may forget to set its content-type or you may forget to include the auth token.

Therefore it deserves to be made into its own function, not just a piece of code:

// This function returns a promise because fetch returns a promise:
function get (url) {
  return fetch(url, {
    method: 'GET',
      headers: {
      'Content-Type': 'application/json',
      Authorization: 'Bearer '   localStorage.getItem('token'),
    },
  })
}

Next is handling of status code 200. You are using an if block. That means making sure all functions that fetch data have the same structure. Again it is error prone because of copy/paste programming.

Since you are setting a state and throwing an error anyway you can handle it in the get() function above:

// This function returns a promise because fetch returns a promise:
async function get (url) {
  let response = await fetch(url, {
    method: 'GET',
      headers: {
      'Content-Type': 'application/json',
      Authorization: 'Bearer '   localStorage.getItem('token'),
    },
  })

  if (response.status !== 200) {
    throw new Error('Server response invalid')
  }
  return response
}

The setServerAlert() will be handled by your outer try/catch block since we are throwing an error.

Now your code is considerably simplified:

const handleLoadInventory = async () => {
  try {
    const _data = await get('http://localhost:4000/api/v1/inventory/')
    const data = await _data.json()

    if (data.items.length !== 0) {
      if (inventoryData.length)
        for (let i = 1; i <= Math.ceil(data.items.length / 10); i  ) {
          pagination.push(i)
        }

      for (let i = 0; i < 10 && i < data.items.length; i  ) {
        showData.push(data.items[i])
      }

      setInventoryData(data.items)
    } else {
      setZeroAlert(true)
    }
  } catch (err) {
    setServerAlert(true)
    console.error(err)
  }
}

Personally I'd even move the _data.json() part into the get() function but I think you get the point.

  • Related