1

What is the difference between Navigate component and navigate from useNavigate() hook?.

if (therapy !== desiredGroupTherapy || required.includes('admin') && !isAdmin) {
    const pathname = generatePath(pageRoutes.DASHBOARD, {
      groupId: desiredGroupId,
      therapy: therapyForValidGroup,
    })
    navigate(pathname, { replace: true })
    // return <Navigate to={pathname} replace />
  }

I have issue with navigate here. How that should work: I redirect to that page, but at first time I have no therapy, so I should redirect to the same page but my therapy now will be equal to therapyForValidGroup. I have custom hook useTherapy() which takes therapy from URL. So at first time when it is undefined it crashes using navigate function. But using Navigate component, it works fine. So what is the difference?

  • please edit you question to be more specific. – Richardson Jun 23 '22 at 19:36
  • 1
    Are you trying to use the `navigate` function ***outside*** a callback or `useEffect` hook? Can you update your post to include a [minimal, complete, and reproducible code example](https://stackoverflow.com/help/minimal-reproducible-example) so we've more context for what the code is doing and what you want to accomplish? – Drew Reese Jun 23 '22 at 19:37
  • The difference is that ```useNavigate``` is used in functional components while ```navigate``` is used in class components – Icekid Jun 23 '22 at 19:38
  • 1
    @Icekid The `useNavigate` hook ***returns*** the `navigate` function, so they are both used in React function components. The only way `navigate` can be used in a class component is if it is first accessed via a function component and passed as a prop to a class component. – Drew Reese Jun 23 '22 at 19:39
  • @DrewReese, yes, just inside `if`. So I have ProtectedRouteWrapper for each page which checks for a lot of different conditions. In this example, after login I should navigate to Dashboard. Dashboard route looks like that: `${BASEPATH}/:therapy/:groupId/dashboard` I get groupId from response, but I have no therapy, so in that ProtectedRouteWrapper I get default value for therapy and want to navigate to the same route where I have been, and now I will have therapy in my URL and if that condition will be false ( and it will be ) then I will just render my children. – Daniel Sadovskiy Jun 23 '22 at 19:41
  • @DrewReese it uses a lot of logic...( – Daniel Sadovskiy Jun 23 '22 at 19:50
  • We just need a [mcve], the minimal amount of code to reproduce the issue. We can't help diagnose or debug code we can't see. – Drew Reese Jun 23 '22 at 19:57
  • @DrewReese https://codesandbox.io/s/tender-herschel-zdzzlo?file=/src/Dashboard.jsx – Daniel Sadovskiy Jun 23 '22 at 22:12
  • Does this help answer your question about the difference between the `navigate` function and the `Navigate` component? https://stackoverflow.com/a/71784911/8690857 – Drew Reese Jun 24 '22 at 00:52
  • @DrewReese could you try the example, please? Look inside `Authorization.jsx`. Why app don't work as expected using `navigate`, but it works good if we use `return ` – Daniel Sadovskiy Jun 24 '22 at 05:25
  • It's because you are calling `navigate` directly in the component body. `Navigate` component works because you can return JSX from the component body to be rendered. Are you preferring to use the `useNavigate` hook and `navigate` function over the `Navigate` component? – Drew Reese Jun 24 '22 at 05:28
  • @DrewReese, yes, how i could use that code with `navigate` from `useNavigate()` hook? – Daniel Sadovskiy Jun 24 '22 at 06:11

1 Answers1

0

The navigate function, when invoked, is a side-effect. The code is calling navigate directly in the body of the component as an unintentional side-effect.

Move the logic into a useEffect hook.

Example:

import React, { useEffect } from "react";
import { generatePath, useParams } from "react-router";
import { useNavigate } from "react-router-dom";
import { usePathPattern } from "./usePathPattern";

export const Authorization = ({ children }) => {
  const params = useParams();
  const navigate = useNavigate();
  const userTherapy = params.therapy;
  const name = params.name;
  const pattern = usePathPattern();

  useEffect(() => {
    if (userTherapy === "undefined" && name) {
      const pathname = generatePath(pattern, {
        name,
        therapy: "TEST"
      });
      navigate(pathname, { replace: true });
    }
  }, [name, navigate, pattern, userTherapy]);

  return children;
};
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • so what is the difference in render order between using `navigate` and `Navigate` component? why we have `no therapy` error with function from hook? – Daniel Sadovskiy Jun 24 '22 at 06:25
  • @DanielSadovskiy `Navigate` is a React component and can be returned from the `Authorization` component body to be rendered. – Drew Reese Jun 24 '22 at 06:27
  • I mean why I have no issue using component, but I have using function? What is going wrong exactly under that mechanism? – Daniel Sadovskiy Jun 24 '22 at 09:06
  • @DanielSadovskiy Using the `navigate` function directly in component body is an unintentional side-effect. I'm presuming the issue you are seeing is *some* RRD invariant error saying it can't navigate yet, or the code is render looping. In either case, you need to wait for the component to be mounted *before* you can issue any imperative navigation actions. – Drew Reese Jun 24 '22 at 15:59