DEV Community

Garrett R. Morris
Garrett R. Morris

Posted on

React Hook Useeffect Has a Missing Dependency useEffect missing dependency, need advice

I am developing a react plugin called use-models, and i have ran into an issue and i'm having trouble determining what is the proper technique for dealing with the issue.

So, basically my plugin is for hooks and it allows you to define some state object with validation, and use input helpers. if you want to hydrate the state, perhaps from a db call or localstorage, you need to call hydrate() with an update object.

So, i wrote a simple function in my plugin:

function hydrate( _state, _errors=false ) {
    console.log('hydrate()');
    setState({...state,..._state});
    if(_errors){
        setErrors({...errors,..._errors});
    }
}
Enter fullscreen mode Exit fullscreen mode

and my intent was for users to use this like so:

useEffect(()=>{
    hydrate({
        name:'Garrett',
        email:'test@test.com',
        newsletter: 'yes'
    });
},[]);
Enter fullscreen mode Exit fullscreen mode

this works exactly how i intended it, however it leads to the dreaded linter warning:

React Hook useEffect has a missing dependency: 'hydrate'

Hmm, so how to solve this:

Should i simply change my example to pass in hydrate as a dependency? this feels wrong to me, as hydrate never changes.

So i thought to solve it at library level, by modifying hydrate:

function hydrate( _state, _errors=false ) {
    console.log('hydrate()');
    return useEffect(()=>{
        setState({...state,..._state});
        if(_errors){
            setErrors({...errors,..._errors});
        }
    },[_state,_errors]);
}
Enter fullscreen mode Exit fullscreen mode

this works to eliminate the warning, but then i realized that users are still going to need to call hydrate() from within useEffect() on their components. Now i'm at a loss for what to do. can anyone give advice? if i pass hydrate as a dependency to useEffect() then the effect is executed on every re-render!

Top comments (3)

Collapse
 
sabbin profile image
Sabin Pandelovitch • Edited

Try wrapping your hydrate function into a useCallback hook, also use the callback in the setState function not the state it self so you don't have to set a dependency to it, the same goes for the Errors state object

const hydrate = useCallback(( _state, _errors=false ) => {
    console.log('hydrate()');
    setState(prevState => ({...prevState,..._state}));
    if(_errors){
        setErrors(prevErros => ({...prevErrors,..._errors}));
    }
},[]);
Enter fullscreen mode Exit fullscreen mode

After that add the hydrate to your useEffect() dependency array,

useEffect(()=>{
    hydrate({
        name:'Garrett',
        email:'test@test.com',
        newsletter: 'yes'
    });
},[hydrate]);
Enter fullscreen mode Exit fullscreen mode

As the hydrate function has no dependencies it will be initialised only once. So your effect should be executed only once.

Please try and see if this helps you

Collapse
 
r3wt profile image
Garrett R. Morris

Ironically this is exactly what i ended up doing. Thanks for sharing though, as someone who is new to hooks, its very helpful to learn about useCallback(). i think now i will refactor much of my code to take advantage of this feature.

Collapse
 
sabbin profile image
Sabin Pandelovitch

useCallback and useMemo are very useful to know. I think I'll post something on this subject as it's good to know when and where to use them