简体   繁体   中英

React router v6 routing issue

I am trying to create a spring boot application with react code inside it.I have my App.js like this.Only the default route is working and other routes are not working.

import './App.css';
import React from 'react';

import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-balham.css';
import "react-datepicker/dist/react-datepicker.css";
import 'react-js-dialog-box/dist/index.css';
import {BrowserRouter, BrowserRouter as Router, Route, Routes} from 'react-router-dom';
import UploadData from './UploadData';
import RoutesOfApplication from './RoutesOfApplication';
import '@szhsin/react-menu/dist/index.css';
import '@szhsin/react-menu/dist/transitions/slide.css';
//const rootElement = document.getElementById("root");

class App extends React.Component {
    render(){
    console.log('In App');
        return(
            
    <BrowserRouter>
      <Routes>
      
        <Route path="/" element={<RoutesOfApplication/>} />
        <Route path="/*" element={<RoutesOfApplication/>} />
        <Route path="/UploadData" element={<UploadData/>}/>
        <Route path="/:id" element={<UploadData/>}/>
      </Routes>
    </BrowserRouter>
        );
    }   

}
export default App;


package.json : "react-dom": "^17.0.2",
    "react": "^17.0.2",
    "react-router-dom": "^6.3.0"

Am i missing something.

It's possible that the path = "/*" on the 2nd path line may be causing the issue. If React went in order of routing, then that "/*" would be catching all of the routes and not processing /UploadData.

If this doesn't work, I noticed that you imported BrowserRouter twice from "react-router-dom", maybe delete the second time you imported it as an alias "BrowserRouter as Router"?

Hope this works!

if you changed the ordering or removed that path, does it work?

The problem here is you have a wildcard path "/*" and a dynamic path "/:id" in the same route.

The "/:id" route is a dynamic route, so react router doesn't care if its an a actual 32 bit unique id, or the word "hello". Therefore, it is a wildcard route ( "/*" ) as well, but with the added functionality of providing you with a parameter called id when using the useParams hook.

In your example, since all the routes are at the same level, the wildcard route will always win due to higher specificity (since it matches itself, the root path "/" , /UploadData and "/:id" ). "/UploadData" can only match itself, "/:id" , and /* so it will always have lower specificity.

To remedy this, you can use relative routing by nesting routes inside routes, and use an index route to match whenever the children don't, instead of a wildcard. Below is an example.

    <BrowserRouter>
      <Routes>
        <Route path="/">
           <Route path="UploadData" element={<UploadData/>}/>
           <Route path=":id" element={<UploadData/>}/>
           <Route index element = {<RoutesOfApplication/>} />
        </Route>
      </Routes>
    </BrowserRouter>

This way, on "/" , "/UploadData" , and "/:id" the right route is applied, and on any routes that don't match, the index is applied. Therefore, our routes are covered with the appropriate logic.

You can read more here on how react router version 6 chooses the right route (based on SPECIFICTY) and how to structure them

Let's understand the components that are rendered with different paths.

    <BrowserRouter>
      <Routes>
        <Route path="/" element={<h1/>Root Route</h1>} />
        <Route path="/*" element={<h1>Catch All Route</h1>} />
        <Route path="/UploadData" element={<h1>Upload Data Route</h1>} />
        <Route path="/:id" element={<h1>Id Route</h1>} />
      </Routes>
    </BrowserRouter>

With your current setup (as shown above) this is what happens:

  • / renders <h1/>Root Route</h1> , which is desired.

  • /UploadData renders <h1>Upload Data Route</h1> , which is also desired.
    Note : /UploadData also matches with /:id and /* paths but because path /UploadData is the more specific to others React Router resolves to /UploadData .

  • /1234 renders <h1>Id Route</h1> because it's more specific compared to /* .

  • /foo/bar renders <h1>Catch All Route</h1> .

NOTE : Order of routes is not important with React Router V6, it's the specificity of the matching paths.

I guess the expectation is that /foo should resolve to the path="/*" route but in reality it resolves to /:id route because React Router doesn't know what your IDs are.

If you want /foo to show the catchall component you can test the validity of the id inside the component for the id route and if the id is not valid you can render the catchall component.

Refer the code snippet below:

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Routes, Route, useParams } from "react-router-dom";

const CatchAllComponent = () => <h1>Catch All Route</h1>;
const IdComponent = () => {
  const { id } = useParams();
  const isIdValid = /[0-9]/.test(id);

  if (isIdValid) {
    return <h1>Id Route</h1>;
  } else {
    return <CatchAllComponent />;
  }
};

ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<h1>Root Route</h1>} />
        <Route path="/UploadData" element={<h1>Upload Data Route</h1>} />
        <Route path="/:id" element={<IdComponent />} />
        <Route path="*" element={<CatchAllComponent />} />
      </Routes>
    </BrowserRouter>
  </React.StrictMode>,
  document.getElementById("root")
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM