Harsh Baid
Harsh Baid

Reputation: 59

React Hook useEffect has a missing dependency: 'execute'

I can't seem to find an answer to this despite trying different things. I keep getting the error:

 Line 18:5:  React Hook useEffect has a missing dependency: 'execute'. Either include it or remove the dependency array  react-hooks/exhaustive-deps
printWarnings

on this file:

import {useEffect, useState} from 'react'

export const createEffect = (fs, dependency) => {
    const[data, setData] = useState({})

    const execute = () => (
        fs().then(res => {
            setData(res)
        }).catch(err => {
            // do some magic
        })
    )

    useEffect(() => {
        execute()
        const interval = setInterval(execute, 15000)
        return(() => clearInterval(interval))
    }, [dependency])

    return(data)
}

The TLDR is I need to make a fetch request to a specific API function defined by fs() either every 15 seconds or when some global state changes, defined by dependency. I also want to capture the data and any errors hence why I'm wrapping the fs() around with a couple of then() and catch() blocks.

The following code gives me the warning at the top when I execute it inside my functional component:

import createEffect from './components/createEffect'
~~~
let api = new api('http://localhost:8080/v1');
const[status, updateStatus] = useState(true);
const summary = createEffect(api.getSummary, status)

Any idea how I can fix this? I'm new to React useEffect and not 100% if this is the right way to go about doing something like this? Specifying execute as a dependency inside my useEffect call causes the app to constantly re-render. I'm running execute() before calling setInterval() because I want the query to run every 15 seconds AND when the component first renders.

For more context: I'm making a dashboard as a sample project and want to query multiple api endpoints every 15 seconds or immediately when some global state changes. If the global state does change, I want to reset my HTTP polling from whatever time that is left back to 15 seconds.

Upvotes: 0

Views: 1137

Answers (2)

Thai Duong Tran
Thai Duong Tran

Reputation: 2522

The linting error is very straight just says exactly what you need to do, either leaving the dependency array of useEffect as empty, or add the execute function into it.

Basically, because you access the execute function inside the effect callback, and as it's created within the same scope as the effect, React requires it to be a dependency.

To resolve the problem with continuous re-rerendering, you need to make your execute function a memoized function by using useCallback

Solving it should be as simple as:

const execute = useCallback(() => (
    fs().then(res => {
        setData(res)
    }).catch(err => {
        // do some magic
    })
), [setData]);

useEffect(() => {
        execute()
        const interval = setInterval(execute, 15000)
        return(() => clearInterval(interval))
    }, [execute])

Upvotes: 3

Y M
Y M

Reputation: 2202

I think you can add execute as a dependency, since the function definition itself isn't changing. Just debug if the component is re-rendering after every call. I think they shouldn't.

Upvotes: 0

Related Questions