Stop using multiple states for status

mrpbennett

Paul Bennett

Posted on March 25, 2022

Stop using multiple states for status

When it comes to fetching API data in React using fetch there can be ways to update the user or run conditional code. This can generally mean using a selection of different states. Which can potentially get messy and complicated.

You could have something like this:

const [data, setData] = useStatus([])
const [success, setSuccess] = useState('')
const [loading, setLoading] = useState('')
const [rejected, setRejected] = useState('')
const [error, setError] = useState('')
Enter fullscreen mode Exit fullscreen mode

Which in turn could be like the following:

useEffect(() => {

    setLoading('loading') // state 1

    fetch('http://some-api-url')
    .then(response => {
        setData(response)
        setSuccess('success') // state 2
    })
    .catch(err => {
        setError(err)
        setRejected('rejected') // state 3
    })

}, [])
Enter fullscreen mode Exit fullscreen mode

With the above we have three states to manage and keep an eye on. When it comes to using this conditionally it's going to be a pain in the ass. Something like this.

if (success === 'success') {
    //do something
} else if ( loading === 'loading' ) {
    // do something
} else if (rejected === 'rejected') {
    // do something
}
Enter fullscreen mode Exit fullscreen mode

Now wouldn't it be easier to use a status state instead of worrying about 3 other states. We can include something like a const [status, setStatus] = useStatus('idle') and remove all the other states apart from the setData and setError we need the error state so we can handle the displaying of error messages.

So now we have the following which is going to be much cleaner and easier to manage.

const [data, setData] = useStatus([])
const [error, setError] = useState('')
const [status, setStatus] = useState('idle')

useEffect(() => {

    setStatus('loading')

    fetch('http://some-api-url')
    .then(response => {
        setData(response)
        setStatus('success')
    })
    .catch(err => {
        setError(err)
        setStatus('rejected')
    })

}, [])

if (status === 'success') {
    // do something
} else if ( status === 'loading' ) {
    // do something
} else if (status === 'rejected') {
    // do something
}
Enter fullscreen mode Exit fullscreen mode

For me this is much a cleaner way of doing things, I know it's not that much different from using multiple states. However, we only have one state to deal with instead of three.

I got inspired to do things this way by Kent C Dodds. More information here

đź’– đź’Ş đź™… đźš©
mrpbennett
Paul Bennett

Posted on March 25, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related