Reactjs how to add variable in URL parameter - javascript

The link from my backend produce ?id= for my frontend to parse using queryString. Is there a way to get this link to load in the frontend?
http://localhost:3000/resetpassword/?id=61bc1fbe3490be4f3594cc3e/?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJfaWQiOiI2MWJjMWZiZTM0OTBiZTRmMzU5NGNjM2UiLCJmaXJzdG5hbWUiOiJPY2VhbiIsImxhc3RuYW1lIjoiUnlhbiIsImVtYWlsIjoib2NlYW5yeWFuNzI1QHlhaG9vLmNvbSIsInBob25lTnVtYmVyIjo2MjgxMTYxNTIyNjMyLCJkb2IiOiIyMDAwLTA3LTI1VDAwOjAwOjAwLjAwMFoiLCJwYXNzd29yZCI6IiQyYiQxMCR6Li9hMHFQYVFzdnNCUEtxc2QuaENlWmI3OWpIYW1VdHdXNmVnSEpLLlhndHFGZzV3djJ0bSIsIl9fdiI6MH0.21irj8fCPQFvCqmp-3E9BJmqwVp81gyQxIW5LgFplMg
App.js
import './App.css';
import { BrowserRouter,
Routes,
Route,
} from "react-router-dom"; //v6
import LandingPage from "./pages/LandingPage/LandingPage";
import ResetPwPage from "./pages/ResetPwPage/ResetPw";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<LandingPage/>}/>
<Route path="/resetpassword/:id/:token" element={<ResetPwPage/>} />
</Routes>
</BrowserRouter>
);
}
export default App;
I tried
<Route path="/resetpassword/?id=:id/?token=:token" element={<ResetPwPage/>} />
But it doesnt work.
I need the link to contain ?id= and ?token= since i need to get the value of id and token in the frontend as required with queryString.
const parsed = queryString.parse(location.search);
console.log(parsed);
//=> {foo: 'bar'}
Any suggestion or alternatives is much appreciated. Thank you!

In react-router-dom the router and routes/paths don't concern themselves with the queryString, they only care about the path part of the URL. In RRDv6 there is a new useSearchParams hook for accessing and reading from the queryString.
path
/resetpassword/?id=61bc1fbe3490be4f3594cc3e&token=eyJ0eX.....
Remove the bits from the path that was trying to read the queryString.
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<LandingPage/>} />
<Route path="/resetpassword" element={<ResetPwPage/>} />
</Routes>
</BrowserRouter>
);
}
ResetPwPage
import { useSearchParams } from 'react-router-dom';
...
const [searchParams] = useSearchParams();
...
const id = searchParams.get("id");
const token = searchParams.get("token");

Related

React-router is not displaying component in the browser

Inside App.js:
import React, { useState } from 'react';
import './App.css';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import Dashboard from './components/Dashboard/Dashboard';
import Preferences from './components/Preferences/Preferences';
import Login from './components/Login/Login';
function App() {
const [token, setToken] = useState();
if(!token) {
return <Login setToken={setToken} />
}
return (
<div className="wrapper">
<h1>Application</h1>
<BrowserRouter>
<Routes>
/*<Route path="/dashboard">*/
<Route path="/dashboard" element={<Dashboard/>} /></Route>
/*<Route path="/preferences">*/
<Route path="/preferences" element={<Preferences/>} /></Route>
</Routes>
</BrowserRouter>
</div>
);
}
export default App;`
Inside Dashboard.js (../src/components/Dashboard/Dashboard.js):
import React from 'react';
export default function Dashboard() {
return(
<h2>Dashboard</h2>
);
}
Url: http://localhost:3000/dashboard
I want to see the Dashboard content along with the App page content (Application and Dashboard headers) when I load the browser. But when I load the browser, it only displays the App page content and getting the same error:
"Matched leaf route at location "/dashboard" does not have an element. This means it will render an <Outlet /> with a null value by default resulting in an "empty" page."
You are using Routes instead of Router. Replace it on your line 3 and in the return().
Source: React-router https://v5.reactrouter.com/web/api/Route
//...
import { BrowserRouter, Route, Router } from 'react-router-dom';
//...
return ( ...
<Router>
/*<Route path="/dashboard">*/
<Route path="/dashboard" element={<Dashboard/>} />
/*<Route path="/preferences">*/
<Route path="/preferences" element={<Preferences/>} />
</Router>
...)
export default App;
Please specify which version of React router you are using, since a lot of the functionality has changed, is it 6.4 or is still 5 ?
Either way, please remove the comments of the routes, I don't think they help at all.
if you have chosen BrowserRouter from the 6.4 version then it should be used like this
import { BrowserRouter, Route } from 'react-router-dom';
return (
<BrowserRouter>
<Route path="/" element={<RootComp />} >
<Route path="dashboard" element={<Dashboard/>} />
<Route path="preferences" element={<Preferences/>} />
</Route>
</BrowserRouter>
)
export default App;
Where <RootComp /> should have an <Outlet /> as children
import { Outlet } from 'react-router-dom';
const RootComp = () => {
return <div><Outlet /></div>
}
export default RootComp;
Again, this is for the latest React Router component, however, I would advise using createBrowserRouter() rather than the old component-based trees, this way you can programatically create and manage the routes in an Object.

how to get last part of pathname using useParams hook in react js

I'm trying to get the param part of this url: http://myapp.com/123 using this code:
import "./styles.css";
import { useParams } from "react-router-dom";
export default function App() {
const { id } = useParams();
console.log("id", id); // undefined. why??
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>{id}</h2>
</div>
);
}
but somehow the id variable is undefined
Configure a router, something like this, the 2 dots and an identifying word.
path="movie/:id" or path="movie/:nameurl". Check which version of dom router you are using, you should use version 6, I have read their documentation and help. With what I said above it should be solved.
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import GenresPage from "../pages/genres";
import Home from "../pages/home";
import Layout from "../pages/Layout";
import Movie from "../pages/movie";
export const AppRoutes = () => {
return (
<Router>
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="movies" element={<GenresPage />} />
<Route path="movie/:id" element={<Movie />} />
</Route>
</Routes>
</Router>
);
};

react components not rendering with routes

I am using the latest version of react router. When I am using routes in my component, They are not rendering anything but When I remove the routes and use simply the component they are working fine. Not able to understand what is going wrong
This do not work and is not rendering anything on "/" or http://localhost:3000/
import React from "react";
import { BrowserRouter as Router, Route, Navigate } from "react-router-dom";
import Users from "./user/pages/Users";
function App() {
return (
<Router>
<Route path="/" exact>
<Users />
</Route>
<Navigate to="/" />
</Router>
);
}
export default App;
This is rendering and working fine.
import React from "react";
import { BrowserRouter as Router, Route, Navigate } from "react-router-dom";
import Users from "./user/pages/Users";
function App() {
return <Users />;
}
export default App;
import React, {useState} from "react";
import { BrowserRouter as Router, Routes, Route, Navigate } from "react-router-dom";
import Users from "./user/pages/Users";
import Profiles from "./Profiles" // this is dummy
function App() {
const [state, setState] = useState(false)
return (
<Router>
<Routes>
<Route path="/" element={<Users />}/>
<Route path="/profiles" element={state ? <Profiles /> : <Navigate to="/" />} />
{/* so you redirect only if your state is false */}
</Routes>
</Router>
);
}
export default App;
It is because, You din't provide which element to render in Route. It has to be mentioned like element={<Users />}. So try like below,
import React from "react";
import { BrowserRouter as Router, Route, Routes, Navigate } from "react-router-dom";
import Users from "./user/pages/Users";
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<Users />} />
<Navigate to="/" />
</Routes>
</Router>
);
}
export default App;
Based on the docs, all Route components should be placed inside a Routes component, which is nested inside the BrowserRouter.
Also, I noticed you use Navigate everytime, even when you are already at the index path. I think this may cause a problem...
So, with that in mind, Change your code to
import React from "react";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Users from "./user/pages/Users";
function App() {
return (
<Router>
<Routes>
<Route path="/">
<Route index element={<Users />} />
</Route>
</Routes>
</Router>
);
}
export default App;
Issue
In react-router-dom#6 the Route component renders its content on the element prop as a ReactNode, a.k.a. JSX, the only valid child of the Route component is another Route component for the case of nesting routes. The Users component should be moved to the element prop.
Also, to render a redirect to a default route, the Navigate component should also be rendered on a generic route.
Solution
Move Users component onto route's element prop.
Move the Navigate component into a generic route and pass the replace prop so issue a redirect.
Example:
function App() {
return (
<Router>
<Route path="/" element={<Users />} />
<Route path="*" element={<Navigate to="/" replace />} />
</Router>
);
}

How to Show two components for a url in react js

below is my app.js code which will show the components based on the url. when user goes to /home, i need to perform some cookie operations. which i'm able to do. Since home component is required for more than one url, every url(/new,/dashboard) performs the cookie operation. Is it normal behavior ?
Below is my code, please let me know if this is react way to write it or not. I'm new to react js.
function App() {
return (
<div className="App">
<Router>
<Navbar />
<Switch>
<Route path="/" exact />
</Switch>
<Route path="/Home">
<Home />
<About />
</Route>
<Route path="/New">
<Home />
<New />
</Route>
<Route path="/Dashboard">
<Home />
<Dashboard />
</Route>
<Route path="/Run/:testid/">
<Run>
</Route>
</Router>
</div>
);
}
export default App;
below is my home component :
import { React, useEffect } from "react";
import { Button } from "./Button";
import { Link } from "react-router-dom";
import "./Navbar.css";
import "./Home.css";
import useQuery from "../hooks/useQuery";
function Home(props) {
const q = useQuery();
console.log(q.get("token"));
//save the token in cookie if url is /home, but since this home component is render for other urls like /new, /dashboard, it gets executed there as well.
return (
<main id="maincontent">
<div className="dashboard-btns">
<Link to="/dashboard" className="btn-mobile">
<Button id="dashboard" buttonStyle="btn--secondary">
Dashboard
</Button>
</Link>
<Link to="/new" className="btn-mobile">
<Button id="new" buttonStyle="btn--secondary">
New
</Button>
</Link>
<hr className="hr-line" />
</div>
</main>
);
}
export default Home;
In the < Home > component save the token in cookie only if url is /home, but since this home component is rendered for other urls like /new, /dashboard, it gets executed there as well. How do i make it get executed only for /home url
If you want the Home component to render on several routes then you can refactor your routes as such, and specify an array of paths for the route rendering Home. The Router component inclusively matches and render routes, in other words, it renders all matching routes.
function App() {
return (
<div className="App">
<Router>
<Navbar />
<Switch>
<Route path="/" exact /> // what is this for?
</Switch>
<Route path={["/Home", "/New", "/Dashboard"]}>
<Home />
</Route>
<Route path="/Home">
<About />
</Route>
<Route path="/New">
<New />
</Route>
<Route path="/Dashboard">
<Dashboard />
</Route>
<Route path="/Run/:testid/">
<Run>
</Route>
</Router>
</div>
);
}
Update
I'm doing some cookie storing and fetching operation in
component. But that should happen only on "/home" url and shouldn't
happen on "/new", "/dashboard" url. How do I do that?
You can check the current path match and issue a side-effect to do the cookie logic on only the "/home" path.
useRouteMatch
The useRouteMatch hook attempts to match the current URL in the same
way that a <Route> would. It’s mostly useful for getting access to the
match data without actually rendering a <Route>.
match will be null if path isn't a match, otherwise it will return a match object.
import { React, useEffect } from "react";
...
import { Link, useRouteMatch } from "react-router-dom";
...
import useQuery from "../hooks/useQuery";
function Home(props) {
const q = useQuery();
console.log(q.get("token"));
const homeMatch = useRouteMatch("/home");
useEffect(() => {
if (homeMatch) {
//save the token in cookie if url is /home and token defined
const token = q.get("token")
}
}, [homeMatch, q]);
return (
...
);
}
First thing is you can use "exact" to prevent that behaviour, Second you should not use two components inside route, what you can do is you can import Home inside New and Dashboard and use it there.
app.js
markdown.js
importing a component
using the imported component

React Router v5: history.push() changes the address bar, but does not change the page

I am trying to redirect a user to a new page if a login is successful in my React app. The redirect is called from the auth service which is not a component. To access the history object outside of my component I followed this example in the React Router FAQ. However, when I call history.push('/pageafterlogin'), the page is not changed and I remain on the login page (based on my Switch I would expect to end up on the 404 page). The URL in the address bar does get changed to /pageafterlogin but the page is not changed from the login page. No errors appear in the console or anything else to indicate my code does not work.
How can I make history.push() also change the page the user is on?
// /src/history.js
import { createBrowserHistory } from 'history';
export default createBrowserHistory();
// /src/App.js
...
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import history from './history';
function App() {
return (
<Router history={history}>
<Switch>
<Route path="/" exact component={HomePage} />
<Route path="/login" exact render={() => <FormWrapper><LoginForm /></FormWrapper>} />
<Route render={() => <h1>404: not found</h1>} />
</Switch>
</Router>
);
}
export default App;
// src/services/auth.service.js
import axios from 'axios';
import history from '../history';
const API_URL = '...';
class AuthService {
login(username, password) {
return axios.post(API_URL + 'login', {
username,
password
}).then(res => {
if (res.status === 200) {
localStorage.setItem('user', JSON.stringify(res.data));
history.push('/pageafterlogin');
}
});
}
}
Instead of using BrowserRouter, use Router from react-router-dom
You could see the example here
import { Router, Route, Switch, useHistory, create } from 'react-router-dom';
import { createBrowserHistory } from 'history';
import React from 'react';
const history = createBrowserHistory();
export default function App() {
return (
<Router history={history}>
<Switch>
<Route path="/" exact component={() => <h1>HomePage</h1>} />
<Route path="/login" exact component={Login} />
<Route render={() => <h1>404: not found</h1>} />
</Switch>
</Router>
);
}
function Login() {
React.useEffect(() => {
history.push('/pageafterlogin')
}, [])
return <h1>Login page</h1>
}
If you are looking for a solution to this in 2022 and are using React V18+,
the solution is that React v18 does not work well with react-router-dom v5.
I have not tried with react-router-dom v6 yet, but downgrading to React V17 solved the issue for me.
I removed StrictMode and it solved the problem
import { Router } from 'react-router-dom';
import { createBrowserHistory } from 'history';
import React from 'react';
const history = createBrowserHistory();
export default function MyApp() {
return (
<Router history={history}></Router>
);
}
I had the same problem when I hadn't specified the vesion of 'history'. You need to use a 4.x version with Router 5.x. For example, I use React v18, history v4.7.2 and react-router-dom v5.3.3 and it works fine.
Try
npm i history#4.7.2

Categories