9

I am in /customerOrders/13 page and from there I try to redirect to /customerOrders/14 using navigate('/customerOrders/14'). Even though the URL is updated, page is not redirected to /customerOrders/14.

Below are code fragments I extracted related to this from the codebase.

App.js

import {
  BrowserRouter,
  Routes,
  Route
} from "react-router-dom";
...
<BrowserRouter>
    <Routes>
        <Route path="customerOrders/:id" element={<CustomerOrderForm />}></Route>
    </Routes>
<Router>

CustomerOrderForm.jsx

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

const CustomerOrderForm = () => {
    let navigate = useNavigate();

    const save = async () => {
        //
        // logic to persist data goes here...
        //

        navigate(`/customerOrders/${customerOrderId}`);
    }
    ...
}
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
Lakmal Premaratne
  • 1,159
  • 7
  • 18
  • 34
  • 1
    Please add the code of the component that is rendered with route `customerOrder/14`. If you are using useEffect in that component, add the id param from route as a dependency to useEffect. – Mohit Kushwaha Jan 25 '22 at 06:02
  • use `import { useNavigate } from 'react-router-dom'; `const history = useNavigate();` then `history('...');` – Sangeet Agarwal Jan 25 '22 at 06:03
  • @SangeetAgarwal I tried this before and I got error: `useNavigate() may be used only in the context of a component.` – Lakmal Premaratne Jan 25 '22 at 08:11
  • @MohitKushwaha I imported `import { useParams } from "react-router-dom";` and then `let id = useParams().id;`. Id is fetched already... but the problem is I cannot redirect from this page to another. – Lakmal Premaratne Jan 25 '22 at 08:13
  • @MohitKushwaha I updated the question with code as you requested. I removed `history` as well. I read [this](https://stackoverflow.com/questions/70491774/usenavigate-may-be-used-only-in-the-context-of-a-router-component) SO question and still no luck. – Lakmal Premaratne Jan 25 '22 at 09:21
  • @LakmalPremaratne but why are you navigating to the same component, I cannot figure out what you are trying to implement. if you want to refresh the page if param (id) changes, then add it as dependency to useEffect. – Mohit Kushwaha Jan 25 '22 at 12:31
  • @MohitKushwaha Thanks for getting back. I am on Customer Order (CO) 14 (`/customerOrders/14`) and from there the user can create a new CO through a modal dialog. When the modal dlg finishes, I want to navigate to newly created CO (say, 15) `/customerOrders/15`. That's the requirement I have to implement. – Lakmal Premaratne Jan 25 '22 at 12:36

2 Answers2

18

When you are on a given route:

<Route path="customerOrders/:id" element={<CustomerOrderForm />} />

and navigating to the same route already rendering the mounted component then the component needs to "listen" for changes to the route, in this case, specifically the id route match param that is updated. Use an useEffect hook with a dependency on the id route match param to rerun any logic depending on it.

import { useNavigate, useParams } from "react-router-dom";

...

const CustomerOrderForm = () => {
  const navigate = useNavigate();
  const { id } = useParams();

  useEffect(() => {
    // rerun logic depending on id value
  }, [id]);

  const save = async () => {
    //
    // logic to persist data goes here...
    //

    navigate(`/customerOrders/${customerOrderId}`);
  };

  ...

};
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
0

This solution is independent of whether you are redirecting inside a component or not:

// 1. history.ts
import { createBrowserHistory } from 'history'
export const history = createBrowserHistory()

// 2. index.tsx
import { unstable_HistoryRouter as HistoryRouter } from "react-router-dom";
import { history } from './history.ts'

root.render(
  <HistoryRouter history={history}>
     </div>Hello React Router Redirect Feature</div>
  </HistoryRouter>
);

// 3. Your handle function
import { history } from './history.ts'

const getRedirected = (pathNext = '/') => {
  historyObject.push(pathNext);
  // or
  // historyObject.replace('/');
}

My environment:
"react": "18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.11.0",
"history": "^5.3.0"

Now you can use the history object in any non-react component function

Roman
  • 19,236
  • 15
  • 93
  • 97