in Switch Route Routing time it's working, but now latest new Routes, Route it not working custom route
I have wrapped the navbar page and home page in HomeLayoutHOC
can anyone help me :) how to do this latest version I try but so many things. no result for this
I want 'HomeLayoutHOC " route instead of "Route"
->client\src\App.JSX :
//HOC
import HomeLayoutHOC from "./HOC/Home.Hoc";
import { Route, Routes } from "react-router-dom";
//Component
import Temp from "./Components/temp";
function App() {
return (
<>
<Routes>
<HomeLayoutHOC path="/" exact element={Temp} /> // <--- I want this to work!
// <Route path="/" element={<Temp />} /> // <-- this working fine
</Routes>
</>
);
}
export default App;
result 👇
screenshot!
->client\src\index.jsx :
import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import "./index.CSS";
import App from "./App";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
-> client\src\HOC\Home.Hoc.jsx
import React from "react";
import { Route } from "react-router-dom";
// Layout
import HomeLayout from "../Layout/Home.Layout";
const HomeLayoutHOC = ({ component: Component, ...rest }) => {
return (
<>
<Route
{...rest}
component={(props) => (
<HomeLayout>
<Component {...props} />
</HomeLayout>
)}
/>
</>
);
};
export default HomeLayoutHOC;
->client\src\Layout\Home.Layout.jsx
import React from "react";
// Components
import Navbar from "../Components/Navbar";
const HomeLayout = (props) => {
return (
<>
<Navbar />
<div className="container mx-auto px-4 lg:px-20 ">{props.children}</div>
</>
);
};
export default HomeLayout;
please give me the possible suggestion for the latest router dom (Routes, Route)
wrapping/composing
How can I spread routeProps to make them available to your rendered Component the latest router dom (Routes, Route)
react-router-dom#6 removed the need, and compatibility, for custom route components. It's an invariant violation to render anything other than a Route or React.Fragment component in the Routes component. Custom route components are replaced with the use of either wrapper components on individual routes wrapping the element being rendered, or by layout route components that can wrap any number of nested Route components.
Wrapper components render the children prop
<Route
path="/"
element={(
<Wrapper>
<Componenet />
</Wrapper>
)}
>
Layout Route components render an Outlet component for nested routes to render their element prop into.
<Route element={<Layout />}>
<Route path="/" element={<Componenet />} />
</Route>
You are asking for the Layout Route version since it seems you want to render the Navbar component as part of a greater layout.
HomeLayout
import React from "react";
import { Outlet } from "react-router-dom";
import Navbar from "../Components/Navbar";
const HomeLayout = () => {
return (
<>
<Navbar />
<div className="container mx-auto px-4 lg:px-20 ">
<Outlet />
</div>
</>
);
};
export default HomeLayout;
App
Render HomeLayout on a pathless route as a Layout Route. The nested Route components render their content into the outlet.
import { Route, Routes } from "react-router-dom";
import HomeLayout from "./path/to/HomeLayout";
import Temp from "./Components/temp";
function App() {
return (
<Routes>
<Route element={<HomeLayout />}>
<Route path="/" element={<Temp />} />
... other routes to render with Home layout and Navbar ...
</Route>
... other routes to render without Home layout and Navbar ...
</Routes>
);
}
An important aspect you should notice here is that RRDv6 removed route props, all the old "props" are now only accessible via React hooks in the routed component, i.e. useNavigate, useLocation, useParams, etc. If you are still using React class-based components they won't be able to use React hooks, and since RRDv6 also no longer exports the withRouter Higher Order Component, well, you will need to roll your own. See What happened to withRouter? I need it! for details.
This question already has answers here:
How do I render components with different layouts/elements using react-router-dom v6
(2 answers)
Closed 8 months ago.
I have a React application with React Router Dom v6 and trying to render the Nav component when the path does NOT match the root "/" but I'm having trouble getting it to work. This is my code:
import { BrowserRouter as Router, Routes, Route, matchPath } from "react-router-dom";
import Nav from "./components/Nav/Nav";
import Home from "./components/Home/Home";
import Contributors from "./components/Contributors/Contributors";
const App = () => {
const match = matchPath({ path: "/", end: true }, "/");
return (
<Router>
{!match ? <Nav /> : null}
<Routes>
<Route path="/" exact element={<Home />} />
<Route path="/contributors" element={<Contributors />} />
</Routes>
</Router>
);
}
export default App;
How should I fix this?
Quick Solution:
You could simply do like below, adding the Nav where you want. I'm not sure if you can know the path in App, since it's not wrapped inside the Router.
import { BrowserRouter as Router, Routes, Route, matchPath } from "react-router-dom";
import Nav from "./components/Nav/Nav";
import Home from "./components/Home/Home";
import Contributors from "./components/Contributors/Contributors";
const App = () => {
return (
<Router>
<Routes>
<Route path="/" exact element={<Home />} />
<Route path="/contributors" element={<><Nav /><Contributors /></>} />
</Routes>
</Router>
);
}
export default App;
Improvement:
And if you want to take it further, instead of doing like above, you could set up a Layout component, like this:
import { Outlet } from "react-router-dom";
import Nav from "../Nav/Nav";
const Layout () => {
return (
<>
<Nav />
<Outlet />
</>
);
};
export default Layout;
And render the routes where you want the Nav trough the Layout:
import { BrowserRouter as Router, Routes, Route, matchPath } from "react-router-dom";
import Home from "./components/Home/Home";
import Contributors from "./components/Contributors/Contributors";
import Layout from "./components/Layout/Layout";
const App = () => {
return (
<Router>
<Routes>
<Route path="/" exact element={<Home />} />
<Route element={<Layout />}>
<Route path="/contributors" element={<Contributors />} />
</Route>
</Routes>
</Router>
);
}
export default App;
Im new at routing on react.JS, however I have been struggling because the simple products.jsx
should return a simple message when I click, but no one is displaying.
Index.JS code
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>
, document.getElementById('root'));
registerServiceWorker();
code at App.JS
import React, { Component } from "react";
import NavBar from "./components/navbar";
import { Route, Routes } from 'react-router-dom';
import Products from "./components/products";
import "./App.css";
class App extends Component {
render() {
return (
<div>
<NavBar />
<Routes>
<Route path= "/products" component={Products}></Route>
</Routes>
</div>
);
}
}
export default App;
nav.jsx
import React from "react";
const NavBar = () => {
return (
<ul>
<li>
Home
</li>
<li>
Products
</li>
<li>
Posts
</li>
<li>
Admin
</li>
</ul>
);
};
export default NavBar;
products.jsx code
const Product = () => {
return <h1>Products</h1>;
};
export default Product;
I dont know basically what i'm missing.
In react-router-dom v6 the Route components render their components on the element prop as JSX.
<Route path="/products" element={<Products />} />
If you are still using v5 and have just mixed up documentation, then in v5 use the Switch instead (Routes replaced Switch in v6) and use the component prop as you were.
<Switch>
<Route path="/products" component={Products} />
</Switch>
If you are using react-router-dom 6, you have to use element instead of component inside of each route like this:
<Routes>
<Route path= "/products" element={<Products/>}></Route>
</Routes>
if you are using react-router-dom 5, you have to use Switch instead of Routes, like this:
<Switch>
<Route path= "/products" component={Products}></Route>
</Switch>
Trying to make certain routes require Authentication.
I have this:
class App extends Component {
render() {
const menuClass = `${this.props.contentMenuClass} col-xs-12 col-md-9`;
return (
<BrowserRouter history={browserHistory}>
<div className="App">
<Header properties={this.props} />
<div className="container-fluid">
<div className="row">
<SideNav />
<div className={menuClass} id="mainContent">
<Switch>
{routes.map(prop =>
(
<Route
path={prop.path}
component={prop.component}
key={prop.id}
render={() => (
!AuthenticationService.IsAutheenticated() ?
<Redirect to="/Login"/>
:
<Route path={prop.path}
component={prop.component}
key={prop.id}/>
)}
/>
))}
</Switch>
</div>
</div>
</div>
{/* <Footer /> */}
</div>
</BrowserRouter>
);
}
}
const mapStateToProps = state => ({
contentMenuClass: state.menu,
});
export default connect(mapStateToProps)(App);
Note: Yes the auth service works as it should.
For every route I am checking if the user is authenticated, if not then I want to redirect them to the login page, if they are then it will land on the first page with the route of "/".
All I am getting is:
react-dom.development.js:14227 The above error occurred in the <Route> component:
in Route (created by App)
in Switch (created by App)
in div (created by App)
in div (created by App)
in div (created by App)
in div (created by App)
in Router (created by BrowserRouter)
in BrowserRouter (created by App)
in App (created by Connect(App))
in Connect(App)
in Provider
Where am I doing this wrong?
A simple solution would be to make a HOC (High Order Component) that wraps all protected routes.
Depending upon how nested your app is, you may want to utilize local state or redux state.
Working example: https://codesandbox.io/s/5m2690nn6n (this uses local state)
routes/index.js
import React from "react";
import { BrowserRouter, Switch, Route } from "react-router-dom";
import Home from "../components/Home";
import Players from "../components/Players";
import Schedule from "../components/Schedule";
import RequireAuth from "../components/RequireAuth";
export default () => (
<BrowserRouter>
<RequireAuth>
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/players" component={Players} />
<Route path="/schedule" component={Schedule} />
</Switch>
</RequireAuth>
</BrowserRouter>
);
components/RequireAuth.js
import React, { Component, Fragment } from "react";
import { withRouter } from "react-router-dom";
import Login from "./Login";
import Header from "./Header";
class RequireAuth extends Component {
state = { isAuthenticated: false };
componentDidMount = () => {
if (!this.state.isAuthenticated) {
this.props.history.push("/");
}
};
componentDidUpdate = (prevProps, prevState) => {
if (
this.props.location.pathname !== prevProps.location.pathname &&
!this.state.isAuthenticated
) {
this.props.history.push("/");
}
};
isAuthed = () => this.setState({ isAuthenticated: true });
unAuth = () => this.setState({ isAuthenticated: false });
render = () =>
!this.state.isAuthenticated ? (
<Login isAuthed={this.isAuthed} />
) : (
<Fragment>
<Header unAuth={this.unAuth} />
{this.props.children}
</Fragment>
);
}
export default withRouter(RequireAuth);
Or, instead of wrapping routes, you can create a protected component that houses protected routes.
Working example: https://codesandbox.io/s/yqo75n896x (uses redux instead of local state).
routes/index.js
import React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import { createStore } from "redux";
import { Provider } from "react-redux";
import Home from "../components/Home";
import Header from "../containers/Header";
import Info from "../components/Info";
import Sponsors from "../components/Sponsors";
import Signin from "../containers/Signin";
import RequireAuth from "../containers/RequireAuth";
import rootReducer from "../reducers";
const store = createStore(rootReducer);
export default () => (
<Provider store={store}>
<BrowserRouter>
<div>
<Header />
<Switch>
<Route exact path="/" component={Home} />
<Route path="/info" component={Info} />
<Route path="/sponsors" component={Sponsors} />
<Route path="/protected" component={RequireAuth} />
<Route path="/signin" component={Signin} />
</Switch>
</div>
</BrowserRouter>
</Provider>
);
containers/RequireAuth.js
import React from "react";
import { Route, Redirect } from "react-router-dom";
import { connect } from "react-redux";
import ShowPlayerRoster from "../components/ShowPlayerRoster";
import ShowPlayerStats from "../components/ShowPlayerStats";
import Schedule from "../components/Schedule";
const RequireAuth = ({ match: { path }, isAuthenticated }) =>
!isAuthenticated ? (
<Redirect to="/signin" />
) : (
<div>
<Route exact path={`${path}/roster`} component={ShowPlayerRoster} />
<Route path={`${path}/roster/:id`} component={ShowPlayerStats} />
<Route path={`${path}/schedule`} component={Schedule} />
</div>
);
export default connect(state => ({
isAuthenticated: state.auth.isAuthenticated
}))(RequireAuth);
You can even get more modular by creating a wrapper function. You would be able to pick and choose any route by simply wrapping over the component. I don't have a codebox example, but it would be similar to this setup.
For example: <Route path="/blog" component={RequireAuth(Blog)} />
You spelled Autheenticated wrong.
Also, this is an assumption because you only provided the stack trace and not the above error, which probably says AuthenticationService.IsAutheenticated is not a function.
I am new to React. I have been trying to declare routes in a file and then use it in another file.
Here is my routes.js
import React from 'react';
import { Route } from 'react-router-dom';
import App from './components/App';
import Template1 from './components/template1';
import Template2 from './components/template2';
import Template3 from './components/template3';
const routes = (
<Route exact path="/" component={App}>
<Route exact path="/sessionstate1" component={Template1} />
<Route exact path="/sessionstate2" component={Template2} />
<Route exact path="/sessionstate3" component={Template3} />
</Route>
)
export default routes
and index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import './styles/css/index.css';
import routes from './routes.js';
ReactDOM.render(
<Router history={browserHistory} routes={routes} />,
document.getElementById('root')
);
I am not getting any errors or warning but the page is not loading. Please tell me what I am missing
Thanks
well i had the same issue a few days ago, and the solution for me was this...
This one of the routes files:
import React from 'react';
import { Route } from 'react-router-dom';
import { ComponentY } from '../components/functionalitys';
export default [
<Route path="/appointment" component={ComponentY} exact key="create" />,
];
This another route file:
import React from 'react';
import { Route } from 'react-router-dom';
import { LoginPage, Register } from '../components/user';
export default [
<Route path="/register" component={Register} exact key="create" />,
<Route path="/login" component={LoginPage} exact strict key="login" />
];
And this is how I imported in the main app.js:
import routesFromFile1 from './the/route';
import routesFromFile2 from './the/other/route';
class App extends Component{
render(){
return(
<div className="wrapper">
<section className="content container-fluid">
<Switch>
<Route exact path="/" component={Home} strict={true} exact={true}/>
<Route path="/500" component={InternalServer} />
{routesFromFile1}
{routesFromFile2}
</Switch>
</section>
</div>
)
}
}
I hope this help Someone! Cheers!!
You don't need to wrap your Routes inside a div. Try something like this:
routes.js
import React from 'react';
import { Router, Route } from 'react-router';
import { Template1, Template2, Template3 } from './templates';
const createRoutes = () => (
<Router>
<Route exact path="/sessionstate1" component={Template1}/>
<Route exact path="/sessionstate2" component={Template2}/>
<Route exact path="/sessionstate3" component={Template3}/>
</Router>
);
export default createRoutes;
index.js
import ReactDOM from 'react-dom';
import createRoutes from './routes';
const routes = createRoutes();
ReactDOM.render(
routes,
document.getElementById('root')
);
index.js:
import LoginRoutes from './login/routes'
let routeConfig = [];
routeConfig = routeConfig.concat(LoginRoutes(store));
<Router routes={routeConfig}/>
routes.js:
export default (store) => {
return [
{path: '/login', component: Login},
{path: '/signup', component: SignUp},
]
}
This way you can add routes from different files and spread your route definitions to different folders that serve the contextual purpose of the route.
The store variable is there in case you want to use redux and want to have an onEnter event on the route. Example:
export default () => {
const sessionEnter = (location) => {
let {appId} = location.params;
store.dispatch(loadApp(appId));
return [
{path: '/apps/:appId', component: App, onEnter: sessionEnter},
]
}
I find onEnter events a good alternative to componentDidMount, data-fetching-wise. Invoking a data fetch on route level makes more sense to me as I see the component as part of the presentation level.
I think the problem is with wrapping the Route inside a div.
Try wrapping them inside a Route like following. Try this fiddle and change the routes wrapper to div.
const routes=(
<Route >
<Route exact path="/sessionstate1" component={Template1}/>
<Route exact path="/sessionstate2" component={Template2}/>
<Route exact path="/sessionstate3" component={Template3}/>
</Route >
)
export default routes;
And import it into index.js
import routes from './routes.js';
ReactDOM.render(
<Router history={browserHistory} routes={routes} />,
document.getElementById('root')
);
With Typescript
Sepate the file for routes as routes.ts
export const routes = [
{ path: '/', component: Home },
{ path: '/auth-callback', component: authCallback },
{ path: '/fetch-data/:startDateIndex?', component: FetchData }
];
In the App.tsx
export function App() {
const routeComponents = routes.map(({ path, component }, key) => <Route exact path={path} component={component} key={key} />);
return (
<Layout>
{routeComponents}
</Layout>
);
}
Layout.tsx
export default (props: { children?: React.ReactNode }) => (
<React.Fragment>
<div>
<NavMenu />
<TopAppBarFixedAdjust>
{props.children}
</TopAppBarFixedAdjust>
</div>
</React.Fragment>
);
I know I'm little late but here my working
here a working demo
my dependencies are
"react": "16.2.0",
"react-dom": "16.2.0",
"react-router-dom": "4.2.2",
"react-scripts": "1.1.0"
create nav.js file as this
this file is responsible for storing all the links for navbar
import React, { Component } from "react";
import { Link } from "react-router-dom";
class Navi extends Component {
render = () => (
<div>
<Link to="/">Go to Home</Link> <br />
<Link to="/about">Go to About</Link> <br />
<Link to="/any-route">404 page</Link>
</div>
);
}
export default Navi;
Then the routes.js file
here you will define all your routes, and your pages where the routes should navigates to
import React, { Component } from "react";
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
// your components
const Home = () => <h1>Home</h1>;
const About = () => <h1>About</h1>;
const MissingPage = () => <h1>404</h1>;
const routes = (
<Switch>
<Route path="/" exact component={Home} />
<Route path="/about" component={About} />
<Route component={MissingPage} />
</Switch>
);
export default routes;
finally here is the code for index.js
import React, { Component } from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import Navi from "./nav";
import routes from "./routes";
// initialize rotues and navi links
const initRoutes = () => (
<Router>
<div>
<Navi />
{routes}
</div>
</Router>
);
const initializedRoutes = initRoutes();
ReactDOM.render(
initializedRoutes,
document.getElementById("root")
);
This is the routing page created
routing page imported
Hope, it will help everyone. click the link to see code.!!
In react-router-dom version 6.x.x
Suppose you have the following URLs in your react app
/
/home
/handlers
/handlers/notes
/handlers/users
you can isolate all routing components related to handlers(including its nested URLs) by:
Define your main routing
<BrowserRouter>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/home" element={<HomePage />} />
<Route path="/handlers/*" element={<AllHandlersPages />} />
</Routes>
</BrowserRouter>
Notice the existence of path="/handlers/*" where we have a wildcard * to tell react-router-dom to match with any nested route too
then
declare AllHandlersPages in another file like this
export function AllHandlersPages() {
return (
<Routes>
<Route>
<Route index element={<HandlersIndexPage />} />
<Route path="notes" element={<NotesPage />} />
<Route path="users" element={<UsersPage />} />
</Route>
</Routes>
);
}
Because <Route /> can't be defined unless it has a parent <Routes /> don't forget to make them nested properly.
Full working Demo
Try it like this way
import React from "react";
import {HashRouter as Router, Route} from 'react-router-dom';
import NoteContainer from "./component/note/index.jsx";
import Header from "./component/common/header.jsx";
const App = (props) => {
return (
<div className="container">
<Header/> {props.children}
</div>
);
};
var x = () => {
return (
<h1>Hello world!</h1>
);
};
module.exports = () => {
return (
<Router>
<App>
<Route path="/" component={NoteContainer}/>
<Route path="/inbox" component={x}/>
</App>
</Router>
);
};
I did it with very simple way. Follow the two steps below.
In App.js
import "bootstrap/dist/css/bootstrap.min.css";
import Header from "./component/common/header";
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import routes from "./routes";
function App() {
return (
<Router>
<section className="container">
<Header />
{routes}
</section>
</Router>
);
}
export default App;
in routes.js
import React, { Component } from "react";
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import Overview from "./component/overview/overview";
import UsersList from "./component/userslist/UsersList";
import FavUserList from "./component/userslist/FavUserList";
const routes = (
<Switch>
<Route exact path="/" component={Overview} />
<Route path="/adduser" component={UsersList} />
<Route path="/favuser" component={FavUserList} />
</Switch>
);
export default routes;
Note: Make sure you import like this
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
In < Header /> component you have to declare navigation link.
i'm starting into react too, and i figured out a way to make what you are looking for.
What i did was inside the app file (which comes default in every project) i imported the routes file, the routes file is located in a folder called approuter (you can name it whatever you want), i'll write some of my code so you can see what i mean
//APP FILE
import AppRouter from './router/approuter'
function App() {
return (
<>
<div className='app' id="mode">
<AppRouter />
</div>
</>
)
}
export default App
//ROUTER FILE/
import { Route, Routes } from 'react-router-dom'}
import Register from "../pages/register"
import Login from "../pages/login"
export default function AppRouter() {
return (
<>
<div>
<Routes>
<Route path="login" element={<Login />}/>
<Route path="register" element={<Register />}/>
</Routes>
</div>
</>
)
}
This actually worked in a project i'm currently working on, i hope this can answer your question
**index.js**
import ReactDOM from "react-dom/client";
import Paths from "./routes/Paths";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<Paths />
</React.StrictMode>
);
**Paths.js**
import LoginSample from "../portal/LoginSample";
import Dashboard from "../portal/Dashboard";
function Paths() {
return (
<Router>
<Routes>
<Route path="/" element={<LoginSample />} />
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
</Router>
);
}
export default Paths;
Also new to react and was running into the same issue. Here is what I tried (obviously different code and structure, but what we're looking for should be the same functionality)
index.js
import React from "react";
import ReactDOM from "react-dom";
import { createHashHistory } from "history";
import { BrowserRouter, Route } from 'react-router-dom';
import routes from "./routes";
const allRoutes = routes;
ReactDOM.render(
allRoutes,
document.getElementById("app")
)
and the routes.js file.
import React from "react";
import { createHashHistory } from "history";
import { BrowserRouter, Route } from 'react-router-dom';
import App from "./pages/App";
import Detail from "./pages/Detail";
import List from "./pages/List";
const routes = (
<BrowserRouter>
<div>
<Route exact path="/" component={ App } />
<Route path="/" component={ List } />
<Route path="/detail/:repo" component={ Detail } />
</div>
</BrowserRouter>
);
export default routes;
Let me know if that works for you.