2

I have a useEffect that I want to avoid the first run. So I did a hook to check if it's the first render:

useFirstRender

import { useRef, useEffect } from 'react';

export function useFirstRender() {
  const firstRender = useRef(true);

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

  return firstRender.current;
}

And I want to use it like that

  const firstRender = useFirstRender();
  const [isOpen, setOpen] = useState<boolean>(false);
 
  useEffect(() => {
    if (firstRender) {
      return;
    }

    /* Rest of logic using `isOpen` dependency */

  }, [isOpen, firstRender]);

Choice 1: With firstRender as useEffect's dependency

This dependency will re-render the useEffect when firstRender become false, so will make it useless.

Choice 2: Without firstRender as useEffect's dependency

This will make the logic working fine, but building it will cause a warning:

Warning: React Hook useEffect has a missing dependency: 'firstRender'. Either include it or remove the dependency array. react-hooks/exhaustive-deps.

What's the best solution ?!

  • Do I have a solution using only logic and development ?
  • I know that I can add a comment // eslint-disable-line to disable that.. But is it normal to do so ? I find it strange to have to do this when it is the expected behavior. Or can I define the fields I want to disable (and keep the original behavior)

Do I miss something ?! Why do a Eslint rule stop you to do something useful ? I know that I don't want that dependency !?

0

1 Answer 1

0

firstRender is a ref value which doesn't trigger a re-render. You don't need it in the dependencies array. But, The Eslint Plgin doesn't know it's a ref until the ref is in the same component not in a seperate reusable hook.

const firstRender = useRef(true)

useEffect(() => {
  if (firstRender.current) doSomething();
  // Here Eslint knows the source of `firstRender` so it won't complain
}, [])
export function useFirstRender() {
  const firstRender = useRef(true);

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

  return firstRender.current;
}

function Component() {
  const firstRender = useFirstRender();
  const [isOpen, setOpen] = useState<boolean>(false);
 
  useEffect(() => {
    if (firstRender) {
      return;
    }

    /* Rest of logic using `isOpen` dependency */

  }, [isOpen, firstRender]);
}

At the second snippet Eslint has access to the current file. It doesn't know what firstRender is. It will complain just in case it's a state. If you are sure about the hook output is a ref. You can safely eslint-ignore-next-line react/ex...... Or you can get rid of the hook and use the ref directly.

Sign up to request clarification or add additional context in comments.

1 Comment

Okay ! Good to know that intern ref are not mandatory on the useEffet dependency array.. It's working fine using a ref direclty on my component. I also tried to return the ref and not firstRender.current on the hook but no-change :/ sad ^^

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.