Home > Net >  React Hook React.useEffect has a missing dependency - I'm using a fn from a context
React Hook React.useEffect has a missing dependency - I'm using a fn from a context

Time:05-09

In my component, I have the following (for brevity I've only included relevant code snippets):

const authContext = useAuthContext();
const projectContext = useProjectContext();


useEffect(() => {
  const loadProject = async (userId: string) => {
    await projectContext.loadProjectsForUser(userId);
  }
  
  if (authContext.user) {
    loadProject(authContext.user.id).catch().finally();
  }
}, [authContext.user]);

However, eslint tells me:

React Hook React.useEffect has a missing dependency: 'projectContext'. Either include it or remove the dependency array.

Can I ignore this or do I need to add projectContext to the dependency list? It has a bunch of other values, so wouldn't this get called each time one of those updates? What's the best way to resolve this?

Thanks

CodePudding user response:

1,just add projectContext to effect dep array, this will trigger effect when projectContext changes, if projectContext never change this way is fine

2, as @Oleg pointed, Move function const loadProject = async (userId: string) => { await projectContext.loadProjectsForUser(userId); } out of useeffect, then projectContext wont update when it is updated, because it will use the value in first render (effect function is not updated when prop/context change), if projectContext never change this way is fine

3, use ref to store projectContext when it's updated, then you do not add dep array, just a ref and another effect

const authContext = useAuthContext();
const projectContext = useProjectContext();

let ref = createRef(projectContext.loadProjectsForUser)

useEffect(() => {
  const loadProject = async (userId: string) => {
    await ref.current(userId);
  }
  
  if (authContext.user) {
    loadProject(authContext.user.id).catch().finally();
  }
}, [authContext.user]);

useEffect(()=>{
  ref.current = projectContext.loadProjectsForUser
},[projectContext.loadProjectsForUser])

CodePudding user response:

You can destructure authContext and projectContext to get only the value you needed in component. Then you can mention only those values which is used in useEffect in dependency array.

const {user} = useAuthContext();
const {loadProjectsForUser} = useProjectContext();

const {id:userId} = user;

useEffect(() => {
  // Some code here
 }, [userId, loadProjectsForUser])

CodePudding user response:

Yes, you'll need to add projectContext to the dependencies, and to make sure it doesn't trigger a project reload on every change inside projectContext you can update your if statement to something like:

if (authContext.user && projectNotLoaded) { // ... }

Shifting the function out of useEffect won't help in this instance.. you'll just have to add the new function to dependencies and it'll fire on every render.

To stop that you'd have to put the new function into a useCallback() which will require the projectContext as a dependency anyway, so you've just shifted the problem.

As to why you'll want to include projectContext with your dependencies there's a great explanation here:

https://betterprogramming.pub/stop-lying-to-react-about-missing-dependencies-10612e9aeeda

  • Related