reactjsreact-routerreact-router-component

React routing within another component V6


Im using Reavt V6 route.

Im struggeling to get my routes inside gamecomponent to work.

visiting /test results in a completly blank page. while it should load crime module within gamecomponent. visiting / renders gamecomponent, but /test does not render gamecomponent and the route within that.

How do i make this to work?

visiting url /crime should result in gamecomponent beeing loaded, and that

<Route path="/test" element={<Crime />} />

should be loaded.

app.js

import React from 'react';
import logo from './logo.svg';
import './App.css';
import GameComponent from './gameComponent.jsx';
import { BrowserRouter as Router } from 'react-router-dom';
import { Routes, Route, Navigate, Outlet, Switch } from 'react-router-dom';
import PrivateRoute from './PrivateRoute';
import Login from './components/login/login.jsx';



function App() {
    
  return (

  <Router>
    <Routes>
       <Route path="/login" element={<Login />} />
       <PrivateRoute  isAuth={true} path="/" component={GameComponent}  redirectTo='/login'/>
    </Routes>
  </Router>
  );
}
export default App;

privateroute:

import React from 'react';
import PropTypes from 'prop-types';
import { Route, Navigate } from 'react-router-dom';
import { useNavigate  } from "react-router-dom";
import Login from './components/login/login.jsx';
import GameComponent from './gameComponent.jsx';


const PrivateRoute = ({ component: Component, redirectTo, isAuth, path, ...props }) => {
    //isAuth = false;
    
    if(!isAuth) {
        return <Navigate to={redirectTo} />;
    }
    return <Route path={path} element={<Component />} />
};

export default PrivateRoute;

gamecomponent:

import React, {Component} from 'react';
//import Component from 'react-dom';
import SideBarRight from './components/game/sideBarRight.jsx';
import SideBarLeft from './components/game/sideBarLeft.jsx';
import Crime from './components/game/crime.jsx';
import Login from './components/login/login.jsx';
import './gameComponent.css';
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
import { BrowserRouter} from "react-router-dom";


class GameComponent extends Component{
 constructor() {
    super();
    this.state = {
    userData: {
        user: {cash:0, bank:0, weapon:'', username: 'test', locationname: 'Bankok',
        defence: 0},
        rankbar: {rankpercent: 50, rank: 'Mafia'},
        }
    }
    
    
    
    
  }


render() {
    return (
    <div className="main">
    <div className="sidebar left">
                <SideBarLeft/>

    </div>
    <div className="middleContentHolder">
     <Route path="/" element={<Crime />} />
    <Route path="/test" element={<Crime />} />
    <Route path="/crime" element={<Crime />} />
    <Route path="/test2" element={<SideBarRight UserData={this.state.userData} />} />


        <div className="col-8">
            <div className="content">
            <div className="header"><span>Test...</span></div>
            
            </div>
        </div>
    </div>
    <div className="sidebar right">
        <SideBarRight UserData={this.state.userData}/>
        </div>
    </div>
    );
  }
    
}



export default GameComponent;

Solution

  • According to React Router documents:

    You can render a element anywhere you need one, including deep within the component tree of another . These will work just the same as any other , except they will automatically build on the path of the route that rendered them. If you do this, make sure to put a * at the end of the parent route's path. Otherwise the parent route won't match the URL when it is longer than the parent route's path, and your descendant won't ever show up.

    You can read more about it here - Descendant Routes

    So, you just need to do 2 little changes:

    app.js

    Add * to yout path in PrivateRoute:

    <Routes>
       <Route path="/login" element={<Login />} />
       <PrivateRoute
          isAuth={true}
          // Here's the trick
          path="/*"
          component={GameComponent}
          redirectTo="/login"
       />
    </Routes>
    

    gamecomponent.jsx

    Wrapper Route with <Routes>:

    <Routes>
       <Route path="/" element={<Crime />} />
       <Route path="/test" element={<Crime />} />
       <Route path="/crime" element={<Crime />} />
       <Route
          path="/test2"
          element={<SideBarRight UserData={this.state.userData} />}
        />
    </Routes>
    

    Here´s a code sample: codesandbox

    You can check it with routes:

    / => show crime component

    /crime => show crime component

    /anticrime => show antcrime component