This question already has an answer here:
Nested routing in react-router-dom V6
(1 answer)
Closed 1 year ago.
I have a folder structure in my project like this :
---login
---main
in the App I implement routing like this that works fine for me :
import { BrowserRouter as Router, Routes, Route} from 'react-router-dom';
<div className="App">
<Router>
<Routes>
<Route path="/" element={<Login />} />
<Route path="/main" element={<Main />} />
</Routes>
</Router>
</div>
but my problem starts here . When I go to the main page, I want to render the nested routing inside of the main page . I code like that but unfortunately nothing work for me fine.
here is the code in my main component .
import {
BrowserRouter as Router,
Routes,
Route,
Outlet,
Link
} from 'react-router-dom';
<
<h1>
hello Home
</h1>
<Link to="/main/child1">
child 1
</Link>||||
<Link to="/main/child2">
child 2
</Link>
<Link to="/">
log out
</Link>
<Outlet />
<Routes>
<Route path="/main/child1" element={<Children1 />} />
<Route path="/main/child2" element={<Children2 />} />
</Routes>
I want to render the child at the under of my main component but nothing happen. and want to url change to "/main/child1" .
I would be really appreciate it if you can explain the detail .
Thanks.
here is the sample code sample is here
You can use the following code:
import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
Link,
useRouteMatch,
useParams
} from "react-router-dom";
export default function App() {
return (
<Router>
<div>
<ul>
<li>
<Link to="/">Login</Link>
</li>
<li>
<Link to="/main">Main</Link>
</li>
</ul>
<Switch>
<Route path="/">
<Login />
</Route>
<Route path="/main">
<Main />
</Route>
</Switch>
</div>
</Router>
);
}
function Login() {
return <h2>LoginPage</h2>;
}
function Main() {
let match = useRouteMatch();
return (
<div>
<h2>Main Page</h2>
<ul>
<li>
<Link to={`${match.url}/children`}>children</Link>
</li>
<li>
<Link to={`${match.url}/child1`}>
Child_One
</Link>
</li>
</ul>
<Switch>
<Route path={`${match.path}/:childId`}>
<Child />
</Route>
<Route path={match.path}>
<h3>Please select a child.</h3>
</Route>
</Switch>
</div>
);
}
function Child() {
let { childId } = useParams();
return <h3>Requested child ID: {childId}</h3>;
}
The Main page has its own with more routes that build on the /main URL path. You can think of the 2nd here as an "index" page for all children of the main page, or the page that is shown when no child is selected.
For more info, please refer: link
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 months ago.
Improve this question
I'm new to web development but I've built a website using react and I can't figure out how to add a page to it. Do I add it in app.js or do I need another file? Are there any examples that can explain this?
For adding a page, You need to install and use the react-router-dom in your react application.
Initially, You need to install react-router-dom. Run a below command to install the same,
npm install react-router-dom
Then configure the routing in App.js. Each route defines a seperate page. The Layout route alone will be in the top layer. That is for Layout setup. We will wrapping all the routes inside the Layout route and in the Layout component we will be providing where the contents of Home and About will be displayed.
App.js
import './App.css';
import { BrowserRouter, Routes, Route } from 'react-router-dom'
import Home from './Components/Home'
import About from './Components/About'
import Layout from './Components/Layout'
function App() {
return (
<div className="App">
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />}>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
</Route>
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
Layout.jsx
import { Outlet, Link } from 'react-router-dom'
export default function Layout() {
return (
<>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Outlet />
</>
)
}
Home.jsx
export default function Home() {
return (
<>
<p>This is Home</p>
</>
)
}
About.jsx
export default function About() {
return (
<>
<p>This is About Us</p>
</>
)
}
You can create components or separate pages based on your requirement. For routing-related stuff, you can use react-router-dom https://v5.reactrouter.com/web/guides/quick-start.
Example :
App.js
import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
export default function App() {
return (
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/users">Users</Link>
</li>
</ul>
</nav>
{/* A <Switch> looks through its children <Route>s and
renders the first one that matches the current URL. */}
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/users">
<Users />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</div>
</Router>
);
}
Home.js
function Home() {
return <h2>Home</h2>;
}
About.js
function About() {
return <h2>About</h2>;
}
Users.js
function Users() {
return <h2>Users</h2>;
}
Trying to create an about page for a website im working on, I found this solution on Stack but it does not work for me. I was using an outdated tutorial for my original code, this is my current code:
About.js:
import React from "react";
import { Link, Route, useMatch } from "react-router-dom";
import SinglePage from "./SinglePage";
const About = () => {
//const match = useMatch('/');
return (
<div className="about__content">
<ul className="about__list">
<li>
<Link to={'about-app'}>About App</Link>
</li>
<li>
<Link to={'about-author'}>About Author</Link>
</li>
</ul>
<Route path={':slug'}>
<SinglePage />
</Route>
</div>
);
};
export default About;
Index.js where I am rendering the component:
import React from "react";
import ReactDOM from "react-dom";
import TodoContainer from "./functionBased/components/TodoContainer"; // Component file
import "./functionBased/App.css"; // Style sheet
import { HashRouter as Router, Routes, Route } from "react-router-dom"; // Router file
import About from "./functionBased/pages/About";
import NotMatch from "./functionBased/pages/NotMatch";
ReactDOM.render(
<React.StrictMode>
<Router>
<Routes>
<Route exact path="/" element={<TodoContainer />} />
<Route path="/about/*" element={<About />} />
<Route path="*" element={<NotMatch />} />
</Routes>
</Router>
</React.StrictMode>,
document.getElementById("root")
);
Issues
The About component is directly rendering a Route component. The Route component can only be rendered by a Routes component or another Route component as a nested route.
The react-router-dom#6 Route components render their content on the element prop.
Solution
Import the Routes component and wrap the descendent Route component rendered by `About.
Render SinglePage on the route's element prop.
Example:
import React from "react";
import { Link, Routes, Route } from "react-router-dom";
import SinglePage from "./SinglePage";
const About = () => {
return (
<div className="about__content">
<ul className="about__list">
<li>
<Link to="about-app">About App</Link>
</li>
<li>
<Link to="about-author">About Author</Link>
</li>
</ul>
<Routes>
<Route path=":slug" element={<SinglePage />} />
</Routes>
</div>
);
};
export default About;
Alternative
You could alternatively move the SinglePage route out to the main router as a nested route (instead of where it is as a descendent route).
Example:
import React from "react";
import { Link, Outlet } from "react-router-dom";
import SinglePage from "./SinglePage";
const About = () => {
return (
<div className="about__content">
<ul className="about__list">
<li>
<Link to="about-app">About App</Link>
</li>
<li>
<Link to="about-author">About Author</Link>
</li>
</ul>
<Outlet />
</div>
);
};
export default About;
...
<Router>
<Routes>
<Route path="/" element={<TodoContainer />} />
<Route path="/about" element={<About />}>
<Route path=":slug" element={<SinglePage />} />
</Route>
<Route path="*" element={<NotMatch />} />
</Routes>
</Router>
You are defining the routes with /about/* and accessing them with about-something which does not exist at all, add \about\author in to for Link.
I'm new to react and I have a weird problem that every time I do npm start, I get on the same
page! how do I change it? (tried with few projects! the same page!)
routing:
import { Redirect, Route, Switch } from "react-router-dom";
import { Page404 } from "./Page404";
import { Login } from "./Login";
import { Logout } from "./Logout";
import { Register } from "./Register";
export const Routing = () => {
return (
<div>
<Switch>
<Route path="/login" component={Login} />
<Route path="/logout" component={Logout} />
<Route path="/register" component={Register} />
<Redirect exact from="/" to="/login" />
<Route component={Page404} />
</Switch>
</div>
);
};
and the default route that I always get is:
http://localhost:3000/login-auth
EVERY time after npm start.
btw that started to happen when I installed firebase.
in this project I'm not even using firebase and it keeps happening
Thanks!
first edit
I've noticed that I didn't mention important parts:
first: I don't have a home component yet (wanted to practice log in pages)
second: the app component: which contain the router {i needed the router that way because the header using it as well}
import "./App.css";
import { Routing } from "./Components/Routing";
import "notyf/notyf.min.css";
import { BrowserRouter } from "react-router-dom";
import { MenuBar } from "./Components/MenuBar/MenuBar.jsx";
function App() {
return (
<div className="App">
<BrowserRouter>
<header>
<MenuBar />
</header>
<body>
<Routing />
</body>
</BrowserRouter>
</div>
);
}
I've tried to uninstall firebase (although I'm not using it in this project)
and it did not work as well
** I SOLVED IT! **
I had a "homepage" setting in my package.json that lead me there for some reason
I'm confused, first of all why didnt you rap up your <Switch></Switch> in <Router/> tag?
Mostly the router file structure is like this
import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
export default function App() {
return (
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/users">Users</Link>
</li>
</ul>
</nav>
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/users">
<Users />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</div>
</Router>
);
}
function Home() {
return <h2>Home</h2>;
}
function About() {
return <h2>About</h2>;
}
function Users() {
return <h2>Users</h2>;
}
I think instead of http://localhost:3000/login-auth, you want to see http://localhost:3000. If that's the problem:
It goes to login page because you have <Redirect exact from="/" to="/login" />
Even if you delete this line, you will still face problems, because I cannot see your home component. Where is it?
And also you need to wrap your routing with <Router> and <Switch> tags as ASWIN CHANDRON noted.
Also, I kindly advise you to update your knowledge to new React syntax. And to use exact keyword. So, instead of <Route path="/login" component={Login} /> use <Route exact path="/login"><Login /></Route>
And also instead of import { Login } from "./Login"; you can type import Login from "./Login";
I've solved it, the problem was in the package.json, i had "homepage" option and it just throw me there after npm start
My App.js:
<Router>
<Header/>
<Switch>
<Route exact path="/" component={HomeScreen} />
<Route exact path="/screenOne" component={OneScreen} />
<Route exact path="/screenTwo" component={TwoScreen} />
</Switch>
</Router>
The <Header /> has three links to the respective components viz. HomeScreen, OneScreen, TwoScreen.
I want my <TwoScreen /> to be exactly like this baseComponent(i.e App.js) where I have some links and when I click those links, the components corresponding to the link/path gets rendered.
What is the best way to approach this?
there is an example on the react-router site that meets your need, under nesting, you can check it out https://reactrouter.com/web/example/nesting (for just web)
But for me, I simply declare them all in one place/component, especially on react-router-native, if you're doing react-native.
below is the example from their website for web
import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
Link,
useParams,
useRouteMatch
} from "react-router-dom";
// Since routes are regular React components, they
// may be rendered anywhere in the app, including in
// child elements.
//
// This helps when it's time to code-split your app
// into multiple bundles because code-splitting a
// React Router app is the same as code-splitting
// any other React app.
export default function NestingExample() {
return (
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/topics">Topics</Link>
</li>
</ul>
<hr />
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/topics">
<Topics />
</Route>
</Switch>
</div>
</Router>
);
}
function Home() {
return (
<div>
<h2>Home</h2>
</div>
);
}
function Topics() {
// The `path` lets us build <Route> paths that are
// relative to the parent route, while the `url` lets
// us build relative links.
let { path, url } = useRouteMatch();
return (
<div>
<h2>Topics</h2>
<ul>
<li>
<Link to={`${url}/rendering`}>Rendering with React</Link>
</li>
<li>
<Link to={`${url}/components`}>Components</Link>
</li>
<li>
<Link to={`${url}/props-v-state`}>Props v. State</Link>
</li>
</ul>
<Switch>
<Route exact path={path}>
<h3>Please select a topic.</h3>
</Route>
<Route path={`${path}/:topicId`}>
<Topic />
</Route>
</Switch>
</div>
);
}
function Topic() {
// The <Route> that rendered this component has a
// path of `/topics/:topicId`. The `:topicId` portion
// of the URL indicates a placeholder that we can
// get from `useParams()`.
let { topicId } = useParams();
return (
<div>
<h3>{topicId}</h3>
</div>
);
}
I am still a newbie to React. So here I am rendering the root component with two routes: Home and About located in functional components: home.js and about.js respectively. However, even after using exact attribute and , the root component keeps on rendering above. I still cannot figure out how to not render the root component when I am redirecting to any of the mentioned routes?
Heres the live demo: https://codesandbox.io/s/vmz6zwq0k7
The Route component is acting like a "placeholder" for the component you want to render when the URL matches. everything above it (parents and siblings) wont get affected.
Given this code example:
render() {
return (
<BrowserRouter>
<div className="App">
<Link to="/home"> Home </Link>{" "}
|
<Link to="/about"> About Us </Link>{" "}
<div>
<Route exact path="/home" component={Home} />
<Route exact path="/about" component={About} />
</div>
</div>
</BrowserRouter>
);
}
This line of code:
<Route exact path="/home" component={Home} />
Is only a "placeholder" for the Home component. It won't render anything only when the path is matching "/home".
When the path will match, the Route component will render the passed component, The Home component in this case.
It will not affect the entire app tree, and for a good reason!
If the entire app would get re-rendered and replaced with the Home component you would loose the navigation links.
I had the same problem looking at the react-routing getting started portion here. https://reactrouter.com/web/guides/quick-start
I placed my Router/BrowserRouter in my App component. Instead place the router in your index.js file like so
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from "react-router-dom";
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>,
document.getElementById('root')
);
Then your app component can look like so and the root route wont be matched if about or users is matched.
import React from "react";
import {
Switch,
Route,
Link
} from "react-router-dom";
export default function App() {
return (
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/users">Users</Link>
</li>
</ul>
</nav>
{/* A <Switch> looks through its children <Route>s and
renders the first one that matches the current URL. */}
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/users">
<Users />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</div>
);
}
function Home() {
return <h2>Home</h2>;
}
function About() {
return <h2>About</h2>;
}
function Users() {
return <h2>Users</h2>;
}