Home > database >  React Router useNavigate with a useEffect hook - proper way to use?
React Router useNavigate with a useEffect hook - proper way to use?

Time:09-15

I'm new to React and trying to make a loading/greeting page that navigates on to the next after a few seconds of being shown. In React Router v6, we have the useNavigate() hook to allow you to control the navigation, and I am using this to successfully call the navigate function by setting a timeout in a useEffect() hook. However, the compiler is complaining that I have a missing dependency. I only want it to run once though, not whenever the navigate changes. What is the best way to do this?

Thanks!

import { useEffect } from "react";
import { useNavigate } from "react-router-dom";

function Greeting(props) {
  const navigate = useNavigate();
  useEffect(() => {
    setTimeout(() => navigate(props.nextPage), 3000);
  }, []);

  return (
    <div className="Greeting">
      <div>Hello World!</div>
    </div>
  );
}

export default Greeting;

Line 9:6: React Hook useEffect has a missing dependency: 'navigate'. Either include it or remove the dependency array react-hooks/exhaustive-deps

CodePudding user response:

The useEffect hook is missing dependencies, both the navigate function and props.nextPage that are referenced in the callback. Add them to the dependency array. Don't forget to return a cleanup function in the case that the component unmounts prior to the timeout expiring on its own.

useEffect(() => {
  const timerId = setTimeout(() => navigate(props.nextPage), 3000);
  return () => clearTimeout(timerId);
}, [navigate, props.nextPage]);

As a general rule you should follow all guidance from the linter. The react-hooks/exhaustive-deps rule is there to help you write better code. Don't disable the rule for that line unless you absolutely know what you are doing and what future consequences may arise if/when you ever update the callback logic and possibly change dependencies.

CodePudding user response:

You can simply hide this warning by adding this:

useEffect(() => {
   setTimeout(() => navigate(props.nextPage), 3000);
  // eslint-disable-next-line
}, []);

This warning is displayed by eslint rules. You can read more about this at How to fix missing dependency warning when using useEffect React Hook

CodePudding user response:

Since navigate is actually a dependency, just add it to the dependency array (The second argument in the useEffect() hook)

Don't worry, the function will still run on mount and it is a safe enough bet that navigate won't change and cause an unwanted 2nd setTimeout

To be really safe, you can actually put in code to make sure the setTimeout is run only once, but it is overkill anyway

CodePudding user response:

Depending on the structure of how you are wanting to set up the project, you can use a useRef hook to eliminate the needed dependency of the useNavigate hook. Or you can add it into the dependency array. Here is an example of doing that.

  const navigate = useRef(useNavigate());

  useEffect(() => {
    const timeout = setTimeout(() => navigate.current(props.nextPage), 3000);

    return () => {
      clearTimeout(timeout);
    };
  }, [props.nextPage]);
  • Related