2
votes

Suppose I am using useEffect to prefetch data on initial rendering:

function myComponent(props) {
    const { fetchSomething } = props;
    ...
    ...
    useEffect(() => {
        fetchSomething();
    }, []);
    ...
    ...
}

My linter warn me for "React Hook useCallback has missing dependencies". It wants me to put fetchSomething inside the dependencies array.
The issue is that even it fetchSomething is going to be changed, I don't want the component to refetch the data. And as I see it, most of the situations where useEffect uses a function, it doesn't really care whether the function is changed.
I don't want to turn off that warning and doesn't like to spread // eslint-disable-next-line react-hooks/exhaustive-deps all over my code.
What is the rational behind such behavior?
It makes me feel insecure while using hooks, as if I am doing something incorrect.

3
Why does your consumer send a prop to load data on mount? Just have a function as a service and call that rather than a prop. If anything your fetchSomething would be a param or data to query off. - Neil

3 Answers

1
votes

You can use useRef or useMemo to store the value.

See https://stackoverflow.com/a/54963730/9351632

0
votes

You can use useRef hook to remember the value of props.fetchSomething on first rendering. This will resolve your issue with eslint

function myComponent(props) {
    const fetchSomethingRef = useRef(props.fetchSomething);

    useEffect(() => {
        fetchSomethingRef.current();
    }, []);
}

The useRef() Hook isn’t just for DOM refs. The “ref” object is a generic container whose current property is mutable and can hold any value, similar to an instance property on a class. more

0
votes

I agree with you that useRef is hacky solution that adds unnecessary complexity. Honestly the best solution I found is to use a conditional inside of useEffect()

function myComponent(props) {
    const { fetchSomething } = props;
    const [fetched, setFetched] = useState(false)
    ...
    ...
    useEffect(() => {
       if(!fetched) {
        fetchSomething();
        setFetched(true)
       }
    }, [fetched, fetchSomething]);
    ...
    ...
}

using the useEffect hook properly is a very complex topic. You can read this very long article about it

https://overreacted.io/a-complete-guide-to-useeffect/

useEffect is still fairly new so there are still competing best practices. I wouldnt recommend useRef tho.