Routing inside a React app with button click

Viewed 61

I am building a basic react app in which clicking a button should open a new page in the same tab. I have used React Router for this but that is not working for me.

I want to redirect to a state say, localhost/test , this is my index.js

import Test from './test/Test'
import { Route } from 'react-router-dom';

const myFirstElement = <>

      <Button onClick={() => window.location.href='test'}>Click me</Button> 

      <Route path='test' element={< Test />}></Route>

</>

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(myFirstElement);

My Test.js contains

const Test = <><h1>Hello React!</h1></>

export default Test;

The problem is above code does not render anything on the screen and it doesn't show any error too. But when I remove the

<Route exact path='/test' element={< Test />}></Route>

above code, a button is rendered on the screen, clicking on the button changes the url but doesn't changes state.

Any help will be appreciated.

2 Answers

Issue

When the index.js file includes just a Route component it fails an invariant that checks if the Route component is rendered directly by a Routes or other Route component, and also fails an invariant check for a routing context being provided by a router component. This is why the code runs when you remove <Route path='/test' element={< Test />} />.

The other issue is with using window.location to change the URL. When this happens it reloads the page, which reloads the React app. You should use react-router-dom hooks and components to navigate within the app.

Solution

The app needs to render at least a router and wrap any Route components in the Routes. Use the useNavigate hook to access the navigate function to issue an imperative navigation action to the "/test" path.

Example:

import { BrowserRouter as Router, Routes, Route, useNavigate } from 'react-router-dom';
import Test from './test/Test'

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

  return (
    <>
      <Button onClick={() => navigate('test')}>Click me</Button>
      <Routes>
        <Route path='test' element={<Test />} />
      </Routes>
    </>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));  root.render(
  <Router>
    <MyFirstElement />
  </Router>
);

If I'm not mistaken, then you definitely need to wrap the application in a BrowserRouter.

import * as React from "react";
import * as ReactDOM from "react-dom";
import App from "./App";
import { BrowserRouter } from "react-router-dom";

ReactDOM.render(
  <BrowserRouter>
    {/* The rest of your app goes here */}
    <App/>
  </BrowserRouter>,
  root
);

Routers must be wrapped with Routes

App component:

import React from 'react';
import {Navigate, Route, Routes, useNavigate} from "react-router-dom";

function App() {
    return (
        <div className={styles.App}>
            <Routes>
                <Route path="/" element={<Test/>}/>
            </Routes>
        </div>
    );
}

export default App;
Related