How to route to a path with parameters in React.js - javascript

I'm trying to make a news-feed website with React.js.
How to make a Router with the news ID?
I'm trying something like this:
<Route path="/news/:id">
{ ( {id} ) => <NewsPiece newsID={id}/> }
</Route>
But it didn't work out. I tried to look it up but didn't find any way convenience.
Below is my App.js being the main file.
import React from 'react';
import NavBar from './components/NavBar'
import Container from './components/Container'
import NewsPiece from './components/NewsPiece'
import Topics from './components/Topics'
import {
BrowserRouter as Router,
Switch,
Route,
} from "react-router-dom";
function App() {
return (
<React.Fragment>
<NavBar/>
<Router>
<Switch>
<Route path="/news/:id">
{ ( {id} ) => <NewsPiece newsID={id}/> }
</Route>
<Route path="/news">
<Topics/>
</Route>
<Route path="/">
<Container/>
</Route>
</Switch>
</Router>
</React.Fragment>
);
}
export default App;

You should simply create a route like this -
App.js -
...
<Switch>
<Route path="/news/:id">
<NewsPiece />
</Route>
<Switch>
...
Now go to your component and access route parameter like this.
components/NewsPiece(assuming it's functional component) - ​
import { useParams } from 'react-router-dom';
function NewPiece = () => {
​....
​const { id } = useParams(); // you'll get the id present in URL route parameter
​....
}
export default NewPiece;
Explanation - react-router-dom provides a hook useParams which extracts all the route parameters present and gives us in an object with key-value pair.
Since you're already getting id from a route parameter you don't need to use extra props newsID for this.

Try this
import React from 'react';
import NavBar from './components/NavBar'
import Container from './components/Container'
import NewsPiece from './components/NewsPiece'
import Topics from './components/Topics'
import {
BrowserRouter as Router,
Switch,
Route,
} from "react-router-dom";
function App() {
return (
<React.Fragment>
<NavBar/>
<Router>
<Switch>
<Route path="/news/:id">
<NewsPiece newsID={id}/>
</Route>
<Route path="/news">
<Topics/>
</Route>
<Route path="/">
<Container/>
</Route>
</Switch>
</Router>
</React.Fragment>
);
}
export default App;
If the error still happens comment the error msg

That's not the correct way to get the route params.
Your route should just be like this.
<Route path="/news/:id">
<NewsPiece/>
</Route>
You will get the value of your param inside the NewsPiece component using props.match.params.id
Here id is the param name you are using.

Try this then
import React from 'react';
import NavBar from './components/NavBar'
import Container from './components/Container'
import NewsPiece from './components/NewsPiece'
import Topics from './components/Topics'
import {
BrowserRouter as Router,
Switch,
Route,
} from "react-router-dom";
function App() {
return (
<React.Fragment>
<NavBar/>
<Router>
<Switch>
<Route
path="/news/:id"
component = {NewsPiece newsID={id}}
</Route>
<Route path="/news">
<Topics/>
</Route>
<Route path="/">
<Container/>
</Route>
</Switch>
</Router>
</React.Fragment>
);
}
export default App;
If the error still continues . Its a problem with your importing method...

Related

React Router Dom, render a component only for some routes [duplicate]

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;

unable to render my components when using with ROUTE in REACTJS

code for app.js .. i have been trying to use ROUTE but unable to render my components
import './App.css';
import Home from './pages/Home';
import Rooms from './pages/Rooms';
import SingleRoom from './pages/SingleRoom';
import Error from './pages/Error';
import { Route, Switch} from 'react-router-dom';
function App() {
return (
<>
<Route exact path="/" component={Home}/>
<Route exact path="/rooms/" component={Rooms}/>
<Route exactpath="/singleroom" component={SingleRoom}/>
</>
);
}
export default App;
You need to wrap your Routes in the Router and Routes components.
This is for react-router-dom v6:
import './App.css';
import Home from './pages/Home';
import Rooms from './pages/Rooms';
import SingleRoom from './pages/SingleRoom';
import Error from './pages/Error';
import { Routes, Route, Switch, BrowserRouter as Router } from 'react-router-dom';
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/rooms/" element={<Rooms />} />
<Route path="/singleroom" element={<SingleRoom />}/>
</Routes>
</Router>
);
}
export default App;
Assuming you already wrapped your app with <Router> inside your index.js file, now every time you use routes You need to wrap them with <Switch>
<Switch>
<Route exact path="/" component={Home}/>
<Route exact path="/rooms/" component={Rooms}/>
<Route exactpath="/singleroom" component={SingleRoom}/>
</Switch>

history.push() updates url but does not render the component

When I try to navigate trougth my project history seems to not work to render other components.
import React from 'react';
import Login from './components/Login.jsx';
import Register from './components/Register';
import Apuntes from './components/Apuntes';
import history from './history/history';
import { Router } from 'react-router';
import { Route } from 'react-router-dom';
export function App() {
return (
<Router history={history}>
<Route exact path='/login' component={Login} />
<Route exact path='/register' component={Register} />
<Route exact path='/apuntes' component={Apuntes} />
</Router>
);
}
Then in my login class I call the history.push('/apuntes') and it changes the url but does nothing more.
The history.js is this:
import { createBrowserHistory } from 'history';
export default createBrowserHistory();
I would like to know how to fix this and get it to show the component depending the url.
this will work :)
//import your components here
import {BrowserRouter as Router,Route, Switch, useHistory } from "react-router-dom";
export function App() {
const history = useHistory();
if (true) { // any condition you need here
history.push("/login");
return (
<Switch>
<Router>
<Route exact path='/login'><Login/></Route>
<Route exact path='/register'><Register/></Route>
<Route exact path='/apuntes'><Apuntes/></Route>
</Router>
</Switch>
);
}
plus you can define a route as default by adding this route at the end of routes.
<Route path="/">
<YourDefaultComponent/>
</Route>

Error "Error: A <Route> is only ever to be used as the child of <Routes> element"

I am trying to use routing for the first time and followed the exact instructions from Udemy:
File App.js:
import { Route } from "react-router-dom";
import Welcome from "./Pages/Welcome";
import Game from "./Pages/Game";
import Leaderboard from "./Pages/Leaderboard";
function App() {
return (
<div>
<Route path = "/welcome">
<Welcome />
</Route>
<Route path = "/game">
<Game />
</Route>
<Route path = "/leaderboard">
<Leaderboard />
</Route>
</div>
);
}
export default App;
File index.js
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from "./App";
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
I get the following error:
Error: A Route is only ever to be used as the child of
element, never rendered directly. Please wrap your Route in a Routes.
Where have I gone wrong?
Yes, in react-router-dom version 6 it is a bit different. Please look as the sample below.
React Router tutorial
import { render } from "react-dom";
import {
BrowserRouter,
Routes,
Route
} from "react-router-dom";
import App from "./App";
import Expenses from "./routes/expenses";
import Invoices from "./routes/invoices";
const rootElement = document.getElementById("root");
render(
<BrowserRouter>
<Routes>
<Route path="/" element={<App />} />
<Route path="expenses" element={<Expenses />} />
<Route path="invoices" element={<Invoices />} />
</Routes>
</BrowserRouter>,
rootElement
);
There was a fairly decent change between versions 5 and 6 of react-router-dom. It appears that the Udemy course/tutorial is using version 5 where all you needed was a Router to provide a routing context and Route components just needed to be rendered within this context. In version 6, however, the Route components now need to be rendered within a Routes component (which is an upgrade from the v5 Switch component).
Introducing Routes
One of the most exciting changes in v6 is the powerful new <Routes>
element. This is a pretty significant upgrade from v5's <Switch>
element with some important new features including relative routing
and linking, automatic route ranking, and nested routes and layouts.
The error message is pretty clear, wrap your Route components in a Routes component. The routes also don't take children (other than other Route components in the case of nested routes), they render the components as JSX on the new element prop.
function App() {
return (
<div>
<Routes>
<Route path="/welcome" element={<Welcome />} />
<Route path="/game" element={<Game />} />
<Route path="/leaderboard" element={<Leaderboard />} />
</Routes>
</div>
);
}
The problem is your react-router-dom version.
Probably it's 5.1 or higher.
You can try (in terminal):
npm install react-router-dom#5.3.0
And then your code will be OK. Or you better rebuild your code according to new react-router-dom.
import React from 'react'
import {BrowserRouter, Route, Routes } from 'react-router-dom'
import './App.css';
import Navbar from './components/Navbar';
import { Home } from './components/screens/Home';
import { Login } from './components/screens/Login';
import { Profile } from './components/screens/Profile';
import { Signup } from './components/screens/Signup';
function App() {
return (
<BrowserRouter>
<Navbar />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<Signup />} />
<Route path="/profile" element={<Profile />} />\
</Routes>
</BrowserRouter>
);
}
export default App;
In the latest version of React, 'Switch' is replaced with 'Routes' and 'component' is replaced with 'element'
Enter image description here
Try to wrap your routes by Routes:
import { Route, Routes } from "react-router-dom";
import Welcome from "./Pages/Welcome";
import Game from "./Pages/Game";
import Leaderboard from "./Pages/Leaderboard";
function App() {
return (
<div>
<Routes>
<Route path = "/welcome">
<Welcome />
</Route>
<Route path = "/game">
<Game />
</Route>
<Route path = "/leaderboard">
<Leaderboard />
</Route>
</Routes>
</div>
);
}
export default App;
I think there are many problems that can lead to that issue.
react-router-dom version 6 no longer supports the use of components directly. Use an element to specify the component you route.
Route has to be a child of Routes
Use the simple snippet.
import logo from './logo.svg';
import './App.css';
import Navbar from './components/Navbar';
import {BrowserRouter, Routes, Route, Link} from 'react-router-dom';
import Homescreen from './screens/Homescreen';
function App() {
return (
<div className="App">
<Navbar/>
<BrowserRouter>
<Routes>
<Route path='/home' element={<Homescreen/>} />
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
The problem right here is that you are using React v5. Since React v6, several changes were included in Router.
So now, to make it work, and as your error message says, you need to wrap your Route element inside a Routes element (Routes now is the equivalent, but an improved version of Switch element). Also, you need to add an "element" prop that accepts JSX instead of wrapping inside the Route element.
So, to make it work, you need to import all these elements like this:
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
That being said, your code should look like this:
<Router>
<Routes>
<Route path="/" element={<Welcome/>}>
</Route>
<Route path="/" element={<Game />}>
</Route>
<Route path="/" element={<Leaderboard />}>
</Route>
</Routes>
</Router>
It's probably because you are using version 6 or higher of react-router-dom.
Try:npm i react-router-dom#5.2.0
And it should work.
In the newer version of react-router-dom, we need to nest the Route inside the Routes. Also, component and exact have been removed in newer version.
I was facing same issue and solve it.
Though I am using
react-router-dom#6
So I had to modify app.js and index.js like below
in index.js
import { BrowserRouter } from "react-router-dom";
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
and app.js
import { Routes, Route } from "react-router-dom";
function App() {
return (
<>
<Header />
<main className="py-3">
<Container>
<Routes>
<Route path="/" element={<HomeScreen />} exact/>
</Routes>
</Container>
</main>
<Footer />
</>
);
}
export default App;
according to official documentation
Now, React uses React Router version 6
For React Router version 6, your index.js file is correct:
File index.js:
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from "./App";
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
But your App.js file is not correct for React Router version 6, so this is the correct one below:
I changed three parts as shown below:
File App.js
// 1. "Routes" is imported
import { Routes, Route } from "react-router-dom";
import Welcome from "./Pages/Welcome";
import Game from "./Pages/Game";
import Leaderboard from "./Pages/Leaderboard";
function App() {
return (
<div> // 2. With "<Routes></Routes>", surround "3 <Route /> tags"
<Routes> // 3. Put an element with a component to each "<Route />"
<Route path = "/welcome" element={<Welcome />} />
<Route path = "/game" element={<Game />} />
<Route path = "/leaderboard" element={<Leaderboard />} />
</Routes>
</div>
);
}
export default App;
Use the element option to set your component instead of nesting it into the route tags. Then wrap all the routes with <Routes></Routes>.
Do not forget to add Routes to your imports
import { Route, Routes } from "react-router-dom";
import Welcome from "./Pages/Welcome";
import Game from "./Pages/Game";
import Leaderboard from "./Pages/Leaderboard";
function App() {
return (
<div>
<Routes>
<Route path = "/welcome" element={<Welcome />}/>
<Route path = "/game" element={<Game />}/>
<Route path = "/leaderboard" element={<Leaderboard />}/>
</Routes>
</div>
);
}
export default App;
Use:
<div>
<Header />
</div>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/profile" element={<Profile />} />
<Route path="/about" element={<About />} />
</Routes>
I know I'm late but there is another way to do nested routes straight from javascript.
first import
import { useRoutes } from "react-router-dom";
secondly, declare your routes. Here is a quick example
function App() {
return useRoutes([
{
path: "/",
element: <Example/>
},
{
path: "/contact",
element: <Example/>
}]);
}
so now you can have unlimited nested components doing it this way.
in your index.js
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
const root = ReactDOM.createRoot(document.getElementById("root")); //where App must rendered in real DOM?in root
root.render(<App />); //jsx code is a special syntax that browser not undrestand it!
and in your App.js
import { BrowserRouter, Routes, Route } from "react-router-dom";
import AllMeetupsPage from "./pages/AllMeetups";
import NewMeetupPage from "./pages/NewMeetup";
import FavoritesPage from "./pages/Favorites";
function App() {
return (
<div>
<BrowserRouter>
<Routes>
<Route path="/" element={<AllMeetupsPage />} />
<Route path="/new-meetup" element={<NewMeetupPage />} />
<Route path="/favorites" element={<FavoritesPage />} />
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
There is another way to fix the version issues:
App.js File:
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Welcome from "./Pages/Welcome";
import Game from "./Pages/Game";
import Leaderboard from "./Pages/Leaderboard";
function App() {
return (<div>
<BrowserRouter>
<Routes>
<Route path = "/Welcome" element={< Welcome/>}/>
<Route path = "/Game" element={< Game/>}/>
<Route path = "/LeaderBoard" element={< LeaderBoard/>}/>
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
Index.js file:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);

Trouble using nested routes in ReactJS

I want to use nested routes in my React app. I have the following MainSwitch:
import React from 'react';
import { Switch, Route } from 'react-router-dom';
import Home from '../Home/Home';
import Dashboard from '../Dashboard/Dashboard';
const MainSwitch = () => {
return (
<Switch>
<Route path='/' component={Home}></Route>
<Route path='/dashboard' component={Dashboard}></Route>
</Switch>
);
}
export default MainSwitch;
This wraps around the app:
import React from 'react';
import MainSwitch from './components/MainSwitch/MainSwitch';
import './css/Colors.css';
import './css/App.css';
function App() {
return (
<div>
<MainSwitch />
</div>
);
}
export default App;
Now in the Home component I have the following:
import React from 'react';
import HomeSwitch from '../HomeSwitch/HomeSwitch';
import NavbarDefault from '../NavbarDefault/NavbarDefault';
const Home = () => {
return (
<div>
<NavbarDefault />
<HomeSwitch />
</div>
);
}
export default Home;
The second switch HomeSwitch is as follows:
import React from 'react';
import { Switch, Route } from 'react-router-dom';
import Landing from '../Landing/Landing';
import Login from '../Login/Login';
import Signup from '../Signup/Signup';
import Pricing from '../Pricing/Pricing';
import NotFound from '../NotFound/NotFound';
const HomeSwitch = () => {
return (
<Switch>
<Route exact path='/' component={Landing}></Route>
<Route exact path='/login' component={Login}></Route>
<Route exat path='/signup' component={Signup}></Route>
<Route exact path='/pricing' component={Pricing}></Route>
<Route exact path="*"><NotFound /></Route>
</Switch>
);
}
export default HomeSwitch;
The reason I use two routers is because pages from Home and Dashboard will have different navigation bars etc.
If I navigate to any of the links in Home there are no issues. But if I try to navigate to /dashboard I get the NotFound page for the 404 error. What am I doing wrong here?
I guess you can just switch the order of the routes:
const MainSwitch = () => {
return (
<Switch>
<Route path='/dashboard' component={Dashboard}></Route>
<Route path='/' component={Home}></Route>
</Switch>
);
}
because this way when you try to go to /dashboard it'll first go through <Route path='/dashboard'. And since these are in a Switch, this path <Route path='/' only matches when the path doesn't start with /dashboard.
Replace <Route exat path='/signup' component={Signup}></Route> by <Route exact path='/signup' component={Signup}></Route>
Pay attention to the exact word instead of exat.
I had a routeing problem here because of the same mistake.

Categories

Resources