2367

With react-router I can use the Link element to create links which are natively handled by react router.

I see internally it calls this.context.transitionTo(...).

I want to do a navigation. Not from a link, but from a dropdown selection (as an example). How can I do this in code? What is this.context?

I saw the Navigation mixin, but can I do this without mixins?

0

51 Answers 51

1
2
8

Just use useNavigate for simplicity with the latest version of react

Newfile.js

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

const Newfile = () => {
    const navigate = useNavigate();
   
    ....

    navigate("yourdesiredlocation");

    ....
}

export default Newfile;

Use useNavigate feature like above in your code.

7

Maybe not the best solution, but it gets the job done:

import { Link } from 'react-router-dom';

// Create functional component Post
export default Post = () => (
    <div className="component post">

        <button className="button delete-post" onClick={() => {
            // ... delete post
            // then redirect, without page reload, by triggering a hidden Link
            document.querySelector('.trigger.go-home').click();
        }}>Delete Post</button>

        <Link to="/" className="trigger go-home hidden"></Link>

    </div>
);

Basically, logic tied to one action (in this case a post deletion) will end up calling a trigger for redirect. This is not ideal, because you will add a DOM node 'trigger' to your markup just so you can conveniently call it when needed. Also, you will directly interact with the DOM, which in a React component may not be desired.

Still, this type of redirect is not required that often. So one or two extra, hidden links in your component markup would not hurt that much, especially if you give them meaningful names.

0
7

This worked for me, and special imports were not needed:

<input 
  type="button" 
  name="back" 
  id="back" 
  class="btn btn-primary" 
  value="Back" 
  onClick={() => { this.props.history.goBack() }} 
/>
0
7

There are a few ways to do programmatic routing in React.js using React Router without using the Link component:

  1. Use the useNavigate hook.

    The useNavigate hook allows you to navigate to a different route programmatically. To use it, you first need to import it from React Router:

    import { useNavigate } from 'react-router-dom';
    

    Then, you can call the useNavigate hook inside of your component to get a function that you can use to navigate to a different route:

    const navigate = useNavigate();
    

    To navigate to a different route, simply call the navigate function with the path of the route that you want to navigate to:

    navigate('/new-page');
    

    You can also pass additional options to the navigate function, such as the state of the route and whether or not to replace the current history entry:

    navigate('/new-page', {
      state: {
        message: 'Hello from the new page!',
      },
      replace: true,
    });
    
  2. Use the history object.

    The history object is a global object that allows you to manipulate the browser's history stack. You can use it to navigate to a different route, go back or forward in history, and more.

    To access the history object, you can use the useHistory hook from React Router:

    import { useHistory } from 'react-router-dom';
    

    Then, you can call the push(), replace(), and goBack() methods on the history object to navigate to different routes:

    history.push('/new-page');
    
    history.replace('/new-page');
    
    history.goBack();
    
  3. Use the <Navigate> component.

    The <Navigate> component is a new component in React Router v6 that allows you to navigate to a different route programmatically. To use it, you first need to import it from React Router:

    import { Navigate } from 'react-router-dom';
    

    Then, you can use the <Navigate> component in your component like this:

    <Navigate to='/new-page' />
    

    This will navigate to the /new-page route immediately.

Which method you choose to use for programmatic routing will depend on your specific needs and preferences. However, all of these methods are valid and can be used to navigate to different routes programmatically without using the Link component.

Here is an example of how to use the useNavigate hook to programmatically navigate to a different route when a button is clicked:

import { useNavigate } from 'react-router-dom';

const Button = () => {
  const navigate = useNavigate();

  const handleClick = () => {
    navigate('/new-page');
  };

  return (
    <button onClick={handleClick}>
      Navigate to new page
    </button>
  );
};

export default Button;

This will navigate to the /new-page route when the button is clicked.

1
  • why the const navigate = useNavigate(); Seems to me it should just be UseNavigate('/new-page').
    – john k
    Commented Nov 16, 2023 at 16:29
5

For React Router v4+

Assuming that you won't be needing to navigate during the initial render itself (for which you can use <Redirect> component), this is what we are doing in our application.

Define an empty route which returns null. This will allow you to get the access to the history object. You need to do this at the top level where your Router is defined.

Now you can do all the things that can be done on history, like history.push(), history.replace(), history.go(-1), etc.!

import React from 'react';
import { HashRouter, Route } from 'react-router-dom';

let routeHistory = null;

export function navigateTo(path) {
  if(routeHistory !== null) {
    routeHistory.push(path);
  }
}

export default function App(props) {
  return (
    <HashRouter hashType="noslash">
      <Route
        render={({ history }) => {
          routeHistory = history;
          return null;
        }}
      />
      {/* Rest of the App */}
    </HashRouter>
  );
}
4

react-router-dom: 5.1.2

  • This site has 3 pages, all of which are rendered dynamically in the browser.

  • Although the page does not ever refresh, notice how React Router keeps the URL up to date as you navigate through the site. This preserves the browser history, making sure things like the back button and bookmarks work properly

  • A Switch looks through all its children elements and renders the first one whose path matches the current URL. Use a any time you have multiple routes, but you want only one of them to render at a time

import React from "react";
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link
} from "react-router-dom";



export default function BasicExample() {
  return (
    <Router>
      <div>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/about">About</Link>
          </li>
          <li>
            <Link to="/dashboard">Dashboard</Link>
          </li>
        </ul>

        <hr />

        <Switch>
          <Route exact path="/">
            <Home />
          </Route>
          <Route path="/about">
            <About />
          </Route>
          <Route path="/dashboard">
            <Dashboard />
          </Route>
        </Switch>
      </div>
    </Router>
  );
}

// You can think of these components as "pages"
// in your app.

function Home() {
  return (
    <div>
      <h2>Home</h2>
    </div>
  );
}

function About() {
  return (
    <div>
      <h2>About</h2>
    </div>
  );
}

function Dashboard() {
  return (
    <div>
      <h2>Dashboard</h2>
    </div>
  );
}```
2
  • Welcome to SO! When you reply to a question with so many answers, try to show the benefits of yours. Commented Dec 28, 2019 at 9:14
  • 1
    This also doesn't answer the question which is how to do it programmatically from imperative js, not with markup. Commented Dec 30, 2019 at 15:32
4

Using the "useHistory" hook is the best option if you're using a newer version of React.

4

This is already mentioned that we can navigate in the last update React Router V6 (doesn't include useHistory) using useNavigate()

import { useNavigate } from 'react-router-dom';

const myComponent = () => {
  const navigate = useNavigate();
  navigate('my_url');
  ...
}

But what I could not find here is calling navigate out of React component like navigating page inside redux-saga function to another page. Just in case, if you have the same question, here is what I found.

In your root component (I call that <App />)

import { useNavigate } from 'react-router-dom';
import useBus from 'use-bus';

const App = () => {
  const navigate = useNavigate();
  useBus('@@ui/navigate', (action) => navigate(action.payload.url), []);
  ...
}

Out of React component (in my case redux-saga function)

import { dispatch } from 'use-bus';

dispatch({ type: '@@ui/navigate', payload: { url: '/404' } });

Hope it's helpful!

0
4

there a lot of hooks and components that provided by latest version of react-router:

Navigate Element

this built-in component by react-router redirected you to the path that you provide to it when it rendered

usage

<Navigate to="/dashboard" />

Navigate element accepts to prop as the route path that you want to navigate to it, and some more props you can checkout this doc: https://reactrouter.com/en/main/components/navigate#navigate

Link element

Link element gives you the possibility to add clickable links like normal anchor

usage

<Link to='/new-page'>new page</Link>

to prop as the route path that you want to navigate when user click on the element, checkout the docs for more https://reactrouter.com/en/main/components/link#link

NavLink element

NavLink is like the Link element with some additional features to get the state of the link, the most use case for this element is When building a navigation menu look at this example :

<NavLink
 to="/home"
 style={({ isActive }) => {
 return isActive ? { color: "plum" } : {};
 }}
 >
 Home
</NavLink>

if the current link is /home, the condition is true, isActive is a boolean that andicate is the current link is the same to the to one that you pass, more details about this one https://reactrouter.com/en/main/components/nav-link

useNavigate hook

useNavigate is hook provided by react-router, this hook return a function that accept the route path and additional options.

usage

const navigate = useNavigate();
const onclickfn = ()=>{
navigate('/my-new-route')
}

when the onclickfn invoked react router redirects you to /my-new-route path

more about this hook here: https://reactrouter.com/en/main/hooks/use-navigate

useSearchParams hook

useSearchParams is hook provided by react-router that help you to read or modify the query of your current URL

usage

let [searchParams, setSearchParams] = useSearchParams();
searchParams.get('key') // to get the value of key
searchParams.set('key','abcd') // to modify the key query to abcd the url should be like: ?key=abcd

more details about this hook here: https://reactrouter.com/en/main/hooks/use-search-params#usesearchparams

3

You can try the onClick event in React and call a function to redirect to the specified location using useNavigate hook of React Router. You can directly use callback function in the onClick handler rather than specifying a different function. You first need to install react router DOM.

npm i react-router-dom

Try the below code

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

const Page = () => {
  const navigate = useNavigate();

  return (
    <button onClick={() => navigate('/pagename')}>
      Go To Page
    </button>
  );
}
1

Simply use useNavigate from react router dom

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

const MYComponent = () => {
    const navigate = useNavigate();

    navigate("Xyz/MYRoutes");

 
}

export default MYComponent;

Use useNavigate feature like above in your code.

1

You can tackle the option you want to let it do this thing.

<select>
 <option onClick={() => <Navigate to="/home" />}> Option 1 </option>
</select>

This you'll find in react-router-dom also you can use the hook, useNavigation()

const navigate = useNavigation();

navigate("/home") // use it onClick or anywhere.
1
   import react from "react";

    // importing navigate from react-router-dom
    import {useNavigate} from "react-router-dom";
    
    function testNavigation() {
    const navigate = useNavigate();
    
    return (
    <>
    <button onClick={navigate("/")}> Test Navigate </button>

    </>
    )
    }

please note: before use nagivate path "/" in onClick make sure you already initial this path to your app.jsx file in your project which is provided react-router-dom in route.

1
  • Thank you for your contribution! It would be very helpful if you could provide a brief explanation of the code you've posted and how it addresses the problem described in the question. This will make your answer more valuable for others who might come across this thread in the future, and will also help the original poster and other readers to understand the solution more clearly. Thanks in advance! If you need further knowledge check out: How To: Write a good answer
    – AztecCodes
    Commented Sep 8, 2023 at 22:29
0

Just using the browser api, independent of any library

const navigate = (to) => {
    window.history.pushState({}, ",", to);
  };

this does not cause full page refresh. you can still use the browser back button

0

There are several ways to navigate programmatically:

  1. Use web history API [https://developer.mozilla.org/en-US/docs/Web/API/History_API] eg: history("/route")
  2. Use callback function
  3. use push from connected-react-router eg: push({ pathname: "/route"})
0

In React Router, you can programmatically navigate to a different route using the useHistory hook (for functional components) or the withRouter HOC (for class components). Here's how you can do it using the useHistory hook:

import React from 'react';
import { useHistory } from 'react-router-dom';

const MyComponent = () => {
  const history = useHistory();

  const handleClick = () => {
    // Navigate to a different route programmatically
    history.push('/new-route');
  };

  return (
    <div>
      <button onClick={handleClick}>Go to New Route</button>
    </div>
  );
};
0

React-router v6.27.0

import all required routing packages from react-router-dom & use them accordingly in your main app component.

import { BrowserRouter, Router, Route, Routes } from "react-router-dom";

function App() {
  return (
    <BrowserRouter>
      <div className="App">
        <Routes>
          <Route path="/" element={<Home />} />
        </Routes>
      </div>
    </BrowserRouter>

  );
}

Now, just create a element i.e.component like here Home, then inside of it navigate in different links:

import { Link } from 'react-router-dom';
function App() {
return (
<>
 <Link to={`/Home`} className="text-blue-500 hover:underline">
                            Go To Home</Link>
</>
)
}
0

Using class components in React Router 6

First, create a function component that handles navigation:

import React from 'react';
import { useNavigate } from 'react-router-dom';

function NavHookButton({ onClick, children, to = '/' }) {
  const navigate = useNavigate();

  function handleNav() {
    navigate(to);
  }

  return (
    <button onClick={() => onClick(handleNav)}>
      {children}
    </button>
  );
}

Next, use in your class and navigate to wherever:

class MyComponent extends React.Component {
  handleSubmit = (navigate) => {
    navigate();
  };

  render() {
    return (
      <div>
        <NavHookButton onClick={this.handleSubmit} to={'/home'}>
          Submit
        </NavHookButton>
      </div>
    );
  }
}
-1

There are already a ton of answers which answer this question appropriately and accurately in the context of react router, but I'd like to take a moment to point out something that I didn't see mentioned in the other answers.

Kind of a stackoverflow trope to recommend doing something a different way than the original question asks, however in this case due to the age of the question I feel like the question would be stated differently in current time.

I'd recommend ditching react-router all together and just pushing to the native browser location, via window.location.href = [your url here], and checking path via regex (or exact) matching window.location.pathname against your intended path.

The simpler answer is usually the best one, and in this case, the use case for React Router is better served by the native Location object API.

4
  • Your answer is good enough but breaks the best practices when using the ReactJs library - You don't want to manipulate DOM directly for many reasons. Commented Nov 22, 2022 at 4:49
  • I've tried doing that in the past, and my code became MUCH more verbose. I eventually had to create an entire routing class just to ensure my application was properly routable. I spent weeks debugging silly bugs because, as it turns out, the history API is very, VERY fussy and counterintuitive. For advanced use cases, it quickly becomes a chore. I still use that routing class I wrote for the project it was made for, but for new projects, React Router is a breath of fresh air. Also, your answer feels out of place here. You should assume the person asking has already considered alternatives. Commented Nov 5, 2024 at 8:16
  • React router is out of place in the current ecosystem and has added bloat in the newer versions. I'm unsure of your particular implementation, but considering most of my applications are SPAs, having a history constant with watchers, changing the URL, and then rendering appropriate components when a change is detected has been significantly more straightforward than any react router implementation I've used in the past, and more intuitive. I struggle to see how it's become more complex for you, what behavior are you doing beyond path, hash, and query changes that constitutes "advanced cases"?
    – methodical
    Commented Nov 9, 2024 at 15:54
  • I also never responded to the original reply since posting, but my approach does not manipulate DOM directly. Triggering state rerenders when location is changed and rendering components based on the path does not break outside of React.
    – methodical
    Commented Nov 9, 2024 at 15:56
-2

layouts/BaseLayout.jsx

import { Outlet } from "react-router-dom";
import Navbar from "../components/Navbar";

const BaseLayout = () => {
    return(
        <div>
        <Navbar/>
        <Outlet/>
        </div>
    )
}

export default BaseLayout

routers/index.jsx

import { createBrowserRouter} from "react-router-dom";
import BaseLayout from "../layouts/BaseLayout";
import HomePage from "../views/HomePage";
import Menu from "../components/Menu"
import Detail from "../components/Detail";

const router = createBrowserRouter([
    {
        element: <BaseLayout/>,
        children:[
            {
                path: "/",
                element: <Menu />,
            },
            {
                path: '/:id',
                element: <Detail/>
            }
        ]

    },
])

export default router

stores/actionType.js

export const FETCH_DATA_FOODS = "food/setFood"

export const FETCH_DATA_FOODS_DETAILS = "food/setDetailFood"

stores/reducers/reducer.js

import { FETCH_DATA_FOODS, FETCH_DATA_FOODS_DETAILS } from "../actionType";

const initialState = {
    foods:[],
    detailFood:{}
};

const foodReducer = (state = initialState, action) => {
    switch(action.type){
        case FETCH_DATA_FOODS:
            return{
                ...state,
                foods: action.payload
            }
        case FETCH_DATA_FOODS_DETAILS:
            return{
                ...state,
                detailFood: action.payload
            }
        default:
            return state
    }
}

export default foodReducer

stores/actionCreator

import { FETCH_DATA_FOODS, FETCH_DATA_FOODS_DETAILS } from "./actionType";

// import { FETCH_DATA_FOODS } from "../actionType";
export const actionFoodSetFoods = (payload) => {
  return {
    type: FETCH_DATA_FOODS,
    payload,
  };
};

export const actionDetailSetDetailFood = (payload) => {
  return {
    type: FETCH_DATA_FOODS_DETAILS,
    payload,
  };
};

export const fetchDataFoods = () => {
  return (dispatch, getState) => {
    fetch("https://maxxkafe.foxhub.space/users")
      .then((response) => {
        if (!response.ok) {
          throw new Error("notOk");
        }
        return response.json();
      })
      .then((data) => {
        // dispatcher({
        //     type: "food/setFood",
        //     payload: data
        // })

        dispatch(actionFoodSetFoods(data));
      });
  };
};

export const fetchDetailDataFood = (id) => {
  return (dispatch, getState) => {
    console.log(id);
    fetch(`https://maxxkafe.foxhub.space/users/${id}`)
      .then((response) => {
        if (!response.ok) {
          throw new Error("gaOkNich");
        }
        console.log(response, ",,,,,,,,");
        return response.json();
      })
      .then((data) => {
        dispatch(actionDetailSetDetailFood(data));
      });
  };
};

stores/index.js

import { legacy_createStore as createStore, combineReducers, applyMiddleware } from 'redux'
import foodReducer from './reducers/foodReducer'
import thunk from "redux-thunk"

const rootReducer = combineReducers({
    foods: foodReducer
});

const store = createStore(rootReducer, applyMiddleware(thunk));

export default store

app.js

import { RouterProvider } from "react-router-dom";
import router from "./routers";
import { Provider } from "react-redux";
import store from "./stores";

const App = () => {
  return (
    <Provider store={store}>
      <RouterProvider router={router} />
    </Provider>
  );
};

export default App;

components/category.jsx

import { useEffect, useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { Link } from "react-router-dom";
import { fetchDataCategories } from "../stores/actionCreate";
import RowCategory from "../views/rowTableCategory";

const Category = () => {
  // const [categories, setCategories] = useState([])
  const { categories } = useSelector((state) => state.categories);
  const dispatcher = useDispatch();
  useEffect(() => {
    // fetch("http://localhost:3003/categories")
    // .then((response) => {
    //     if(!response.ok){
    //         throw new Error ("gaOkNich")
    //     }
    //     return response.json()
    // })
    // .then((data) => {
    //     setCategories(data)
    // })
    dispatcher(fetchDataCategories());
  }, []);
  return (
    <section className="mt-12">
      <div className="flex mr-20 mb-4">
        <Link to={'/add-Form'} className="flex ml-auto text-white bg-red-500 border-0 py-2 px-6 focus:outline-none hover:bg-red-600 rounded">
          Create Category
        </Link>
      </div>
      <div className="overflow-hidden rounded-lg border border-gray-200 shadow-md m-5">
        <table className="w-full border-collapse bg-white text-left text-sm text-gray-500">
          <thead className="bg-gray-50">
            <tr>
              <th scope="col" className="px-6 py-4 font-medium text-gray-900">
                Name
              </th>
              <th scope="col" className="px-6 py-4 font-medium text-gray-900">
                Created At
              </th>
              <th scope="col" className="px-6 py-4 font-medium text-gray-900">
                Updated At
              </th>
              <th
                scope="col"
                className="px-6 py-4 font-medium text-gray-900"
              ></th>
            </tr>
          </thead>
          <tbody className="divide-y divide-gray-100 border-t border-gray-100">
            {categories.map((el) => {
              return <RowCategory key={el.id} el={el} />;
            })}
          </tbody>
        </table>
      </div>
    </section>
  );
};

export default Category;

components/login.jsx

import { useState } from "react";
import { useNavigate } from "react-router-dom";
import { useDispatch } from "react-redux";
import { fetchDataFoods, login } from "../stores/actionCreate";

const Login = () => {
  const input = {
    email: "",
    password: "",
  };
  const [values, setValues] = useState(input);
  // const [password, setPassword] = useState('')
  // const {admin} = useSelector((state) => state.admin)

  const dispatcher = useDispatch();
  const movePage = useNavigate();

  const handleChange = (event) => {
    const { name, value } = event.target;
    setValues({
      ...values,
      [name]: value,
    });
    console.log(value);
  };

  const handleLogin = async (event) => {
    event.preventDefault();
    try {
      await dispatcher(login(values));
      await dispatcher(fetchDataFoods());
      movePage("/home");
    } catch (error) {
      console.log(error);
    }
  };

  return (
    <section className="font-mono bg-white-400 mt-[10rem]">
      <div className="container mx-auto">
        <div className="flex justify-center px-6 my-12">
          <div className="w-full xl:w-3/4 lg:w-11/12 flex justify-center">
            <div className="w-full lg:w-7/12 bg-white p-5 rounded-lg lg:rounded-l-none">
              <h3 className="pt-4 text-2xl text-center">Login Your Account!</h3>
              <form
                className="px-8 pt-6 pb-8 mb-4 bg-white rounded"
                onSubmit={handleLogin}
              >
                <div className="mb-4">
                  <label
                    className="block mb-2 text-sm font-bold text-gray-700"
                    htmlFor="email"
                  >
                    Email
                  </label>
                  <input
                    className="w-full px-3 py-2 mb-3 text-sm leading-tight text-gray-700 border rounded shadow appearance-none focus:outline-none focus:shadow-outline"
                    id="email"
                    type="email"
                    name="email"
                    placeholder="Email"
                    // onChange={(event) => setValues({email: event.target.value})}
                    onChange={handleChange}
                    value={values.email.email}
                  />
                </div>

                <div className="mb-4 md:flex md:justify-between">
                  <div className="mb-4 md:mr-2 md:mb-0">
                    <label
                      className="block mb-2 text-sm font-bold text-gray-700"
                      htmlFor="password"
                    >
                      Password
                    </label>
                    <input
                      className="w-full px-3 py-2 mb-3 text-sm leading-tight text-gray-700 border  rounded shadow appearance-none focus:outline-none focus:shadow-outline"
                      id="password"
                      type="password"
                      name="password"
                      placeholder="Password"
                      onChange={handleChange}
                      value={values.password}
                      // onChange={(event) => setValues({password: event.target.value})}
                    />
                  </div>
                </div>
                <div className="mb-4 md:flex md:justify-between"></div>
                <div className="mb-6 text-center">
                  <button
                    className="w-full px-4 py-2 font-bold text-white bg-blue-500 rounded-full hover:bg-blue-700 focus:outline-none focus:shadow-outline"
                    type="submit"
                  >
                    Login
                  </button>
                </div>
              </form>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
};
export default Login;
1
  • a lot of code not related to the answer to the question... you could at least comment what you're trying to demonstrate here Commented Feb 2, 2023 at 18:31
-4

Simply just use :

this.props.history.push('/where/to/go');
1
  • This answer is not clear and useful. I think everything have been answered above clearly and explained in every version of React and React Router. Please add more information if you think your answer is useful and better than them. Best regards Arash Yazdani Commented Feb 18, 2022 at 15:48
1
2

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.