Skip to content

Tag: javascript

useEffectlessState for data fetching with React hooks

Have you ever been into a situation where you wanted to do something with your state inside useEffect hook but didn’t want to put it into a dependency array?

react-hooks/exhaustive-deps is an excellent guard when working with primitive values, but as soon as you have an object in the state, it might stay on your way.

Let me show you some code, which requires state handling in the way I’ve described above.

type FetchInfo =
    | { state: 'LOADING' }
    | { state: 'LOADED' }
    | { state: 'ERROR'; error: Error; statusCode: number | undefined }
    | { state: 'INITIAL' }

interface StateType {
    fetchInfo: FetchInfo
    input: string | undefined
    value: Value
}

export const VerySpecialComponent: React.FC<{ input: string }> = ({ input }) => {
    const [state, setState] = React.useState<StateType>({
        fetchInfo: { state: 'INITIAL' },
        input: undefined,
        value: undefined,
    })

    React.useEffect(() => {
        if (state.fetchInfo.state === 'LOADING' || state.input === input) {
            return
        }

        setState((state) => ({
            ...state,
            fetchInfo: { state: 'LOADING' },
            input,
        }))

        fetchStuff(input).then((result) => {
            setState((state) => ({
                ...state,
                value: result,
                fetchInfo: { state: 'LOADED' },
            }))
        })
    }, [input, state, setState])

    return <div>{state.value}</div>
}

This code looks quite straightforward, still let me elaborate on it.

Read more: useEffectlessState for data fetching with React hooks