JB Cooper
JB Cooper

Reputation: 109

Using React router (v6) why can't I call useNavigate directly?

I am new to React JS and a not 100% familiar with TypeScript. As I am learning I have found myself unable to understand an odd 'quirk'.

My code is as follows and my question is "Why do I have to make a const for useNavigate and then call it inside my method?

import { useNavigate } from 'react-router-dom';
...
 const navigate = useNavigate();
  const handleAskQuestionClick = () => {
    navigate('ask');
  };
...

What am I missing and why can't it be like this?

  const handleAskQuestionClick = () => {
    useNavigate('ask');
  };

Upvotes: 2

Views: 4444

Answers (1)

Linda Paiste
Linda Paiste

Reputation: 42170

There are two aspects to explain here. One is why you cannot call useNavigate with an argument and the other is why you cannot call useNavigate inside of another function.

useNavigate is a React hook. The rules of hooks dictate that you must call all hooks at the top level of your component. They cannot be called conditionally and they cannot be called inside of a callback like your handleAskQuestionClick function.

useNavigate needs to be a hook because it internally relies on the useContext hook to access your router state through React context (The BrowserRouter component is a context provider). It cannot be just a plain function because then it would be violating the rules of hooks itself. So react-router gives you this useNavigate hook which accesses your router state and returns a plain function which is bound to that state. The function that is returned from useNavigate can be called in a callback because it is not a hook.

Hooks cannot be called conditionally, so it would not make sense to do something like uesNavigate('ask') unless you wanted to navigate to that page immediately when the component is rendered (a redirect).

Upvotes: 2

Related Questions