react router dom: redirect and router: all urls are getting redirected, how to stop - react-router-dom

I have the following reactjs code.
I am using react-router-dom V5
import React from "react";
import ReactDOM from "react-dom";
import { createBrowserHistory } from "history";
import { Router, Route, Switch, Redirect } from "react-router-dom";
import Login from "./views/User/Login";
import Signup from "./views/User/SignUp";
import ForgotPassword from "./views/User/ForgotPassword";
import ResetPassword from "./views/User/ResetPassword";
const hist = createBrowserHistory();
ReactDOM.render(
<Router history={hist}>
<Route path="/signup" component={Signup} />
<Route path="/login" component={Login} />
<Route path="/forgot-password" component={ForgotPassword} />
<Route path="/rest-auth/password/reset/confirm/:uidb64([0-9A-Za-z_\-]+)/:token([0-9A-Za-z]{1,20}-[0-9A-Za-z]{1,50})" component={ResetPassword}/
<Redirect from="/" to="/login" />
</Router>,
document.getElementById("root")
);
Here any url i open in browser it gets redirected to /login
eg: I open /signup it gets redirected to /login
the link works but when i open any url in the browser it gets redirected to /login

I found the reason is not using switch. If i use switch it worked
import React from "react";
import ReactDOM from "react-dom";
import { createBrowserHistory } from "history";
import { Router, Route, Switch, Redirect } from "react-router-dom";
import Login from "./views/User/Login";
import Signup from "./views/User/SignUp";
import ForgotPassword from "./views/User/ForgotPassword";
import ResetPassword from "./views/User/ResetPassword";
const hist = createBrowserHistory();
ReactDOM.render(
<Router history={hist}>
<Switch>
<Route path="/signup" component={Signup} />
<Route path="/login" component={Login} />
<Route path="/forgot-password" component={ForgotPassword} />
<Route path="/rest-auth/password/reset/confirm/:uidb64([0-9A-Za-z_\-]+)/:token([0-9A-Za-z]{1,20}-[0-9A-Za-z]{1,50})" component={ResetPassword}/
<Redirect from="/" to="/login" />
</Switch>
</Router>,
document.getElementById("root")
);
Also Route and Redirect should be directly below the Switch else Switch will not work.
Example
<Router history={hist}>
<Switch>
<>
<Route path="/signup" component={Signup} />
<Route path="/login" component={Login} />
<Route path="/forgot-password" component={ForgotPassword} />
<Route path="/rest-auth/password/reset/confirm/:uidb64([0-9A-Za-z_\-]+)/:token([0-9A-Za-z]{1,20}-[0-9A-Za-z]{1,50})" component={ResetPassword}/
<Redirect from="/" to="/login" />
</>
</Switch>
</Router>,
Switch does not have any affect here, so if we try to enter in browser /signup it also matches / so it goes to /login

Related

Uncaught Error: A <Route> is only ever to be used as the child of <Routes> element, never rendered directly. Please wrap your <Route> in a <Routes>

After implemented Private Route I keep getting this error.
The problem appears when Im trying to get to the Profile page that nested in the .
App.js
import './App.css';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import LoginPage from './pages/LoginPage';
import SignUpPage from './pages/SignUpPage';
import ProfilePage from './pages/ProfilePage';
import HomePage from './pages/HomePage';
import AboutPage from './pages/AboutPage';
import AdditionalItemPage from './pages/AdditionalItemPage';
import ReturnOfVehiclePage from './pages/ReturnOfVehiclePage';
import PolicyPage from './pages/PolicyPage';
import CarPage from './pages/CarPage';
import CarListPage from './pages/CarsListPage';
import NavBar from './NavBar';
import Footer from './Footer';
import NotFoundPage from './pages/NotFoundPage';
import { PrivateRoute } from './auth/PrivateRoute';
function App() {
return (
<BrowserRouter>
<div className="App">
<NavBar />
<div>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/login" element={<LoginPage />} />
<Route path="/signup" element={<SignUpPage />} />
<Route path="/about" element={<AboutPage />} />
<Route path="/cars" element={<CarListPage />} />
<Route path="/cars/:carId" element={<CarPage />} />
<Route path="/additional-item" element={<AdditionalItemPage />} />
<Route path="/return-vehicle" element={<ReturnOfVehiclePage />} />
<Route path="/policy" element={<PolicyPage />} />
<Route
path="/profile"
element={
<PrivateRoute>
<ProfilePage />
</PrivateRoute>
}
/>
<Route path="*" element={<NotFoundPage />} />
</Routes>
</div>
<Footer />
</div>
</BrowserRouter>
);
}
export default App;
PrivateRoute.js comp
import { Route, Navigate } from 'react-router-dom';
import { useUser } from './useUser';
export const PrivateRoute = (props) => {
const user = useUser();
if (!user) return <Navigate to="/login" />;
return <Route {...props} />;
};
I've already tried to wrap everyting I though of in the
The actual Profile paga into Routes
The PrivteRoute into Routes
The Route into another Routes
Creating another Routes, separeted with the 1st one.
If remove PrivateRoute, everything works fine but it s not the solution I'm looking for.
You just didn't implement it properly , just change your PrivateRoute.js component like this :
import { Navigate } from 'react-router-dom';
import { useUser } from './useUser';
function PrivateRoute({ children }) {
const user = useUser();
return user ? children : <Navigate to="/login" />;
}
The error message is accurate in that a Route must be directly placed within a Routes wrap. To get around this, simply create a 2nd top-level Routes wrap and move the Route logic out of your PrivateRoute.tsx file.
Consider this example sandbox I created with some slight modifications to your code. You can switch user to false/true to see how the /profile private route reacts as expected.
Here's the bare-bones implementation:
App.tsx
import { BrowserRouter, Route, Routes } from "react-router-dom";
import PrivateRoutes from "./PrivateRoutes";
function App() {
return (
<BrowserRouter>
<div className="App">
<div>
<Routes>
<Route path="/" element={<div>Hello World</div>} />
</Routes>
<PrivateRoutes /> {/* <---- all private routes ---- */}
</div>
</div>
</BrowserRouter>
);
}
export default App;
PrivateRoutes.tsx
import { Route, Routes } from "react-router-dom";
import PrivateRoute from "./PrivateRoute";
export default function PrivateRoutes() {
return (
<Routes>
<Route
path="/profile"
element={
<PrivateRoute>
<div>Private Profile</div>
</PrivateRoute>
}
/>
</Routes>
);
}
PrivateRoute.tsx
import { ReactNode } from "react";
import { Navigate } from "react-router-dom";
interface PropsI {
children: ReactNode;
}
export default function PrivateRoute({ children }: PropsI) {
const user = false;
if (!user) return <Navigate to="/fail" />;
return <>{children}</>;
}

How can I navigate to Sign in page if the user is not login?

I want to navigate to the Signin page if the user is not login. But if the user is login then it will automatically navigate to home page, but I am not able to navigate to Sign in page when user is not login. I am pasting the code below. Kindly help me if you can.
Here is my App.js code
import React from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import "./App.css";
import { Home } from "./containers/Home";
import { Signin } from "./containers/Signin";
import { Signup } from "./containers/Signup";
import PrivateRoute from "./components/HOC/PrivateRoute";
function App() {
return (
<div className="App">
<BrowserRouter>
<Routes>
<PrivateRoute path="/" element={<Home />} />
<Route path="/signin" element={<Signin />} />
<Route path="/signup" element={<Signup />} />
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
Private route code is below
import React from "react";
import { Route , Navigate } from "react-router-dom";
const PrivateRoute = ({element:Component , ...rest})=>{
return <Route {...rest} element={(props)=>{
const token = window.localStorage.getItem('token');
if(token){
return <Component {...props} />
}else{
return <Navigate to={'/signin'}/>
}
}} />
}
export default PrivateRoute;`
I have tried many things but they didn't work. Kindly help me
You should add exact to your path '/' else any path starting by '/' will be routed to your Home component:
<PrivateRoute path="/" exact element={<Home />} />

how to set condition in react router DOM version 6?

I want to convert this code which has been written in react router v5 to v6 but I don't know how to do it, in general I want to set if the user doesn't have an account, redirect them to registration page an so on.
I'm aware of switch change and redirect the only problem is in this line of code :
<Route exact path="/">
{user ? <Home /> : <Redirect to="/register" />}
</Route>
the whole code:
import "./app.scss";
import Home from "./pages/home/Home";
import Register from "./pages/register/Register";
import Watch from "./pages/watch/Watch";
import Login from "./pages/login/Login";
import {
BrowserRouter as Router,
Switch,
Route,
Redirect,
} from "react-router-dom";
import { useContext } from "react";
import { AuthContext } from "./authContext/AuthContext";
const App = () => {
const { user } = useContext(AuthContext);
return (
<Router>
<Switch>
<Route exact path="/">
{user ? <Home /> : <Redirect to="/register" />}
</Route>
<Route path="/register">
{!user ? <Register /> : <Redirect to="/" />}
</Route>
<Route path="/login">{!user ? <Login /> : <Redirect to="/" />}</Route>
{user && (
<>
<Route path="/movies">
<Home type="movie" />
</Route>
<Route path="/series">
<Home type="series" />
</Route>
<Route path="/watch">
<Watch />
</Route>
</>
)}
</Switch>
</Router>
);
};
export default App;
You can use the element prop of v6, you don't need to use an exact prop on <Route path="/"> anymore. This is because all paths match exactly by default. If you want to match more of the URL because you have child routes use a trailing * as <Route path="/*" />.
import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
.
.
.
return (
<BrowserRouter>
<Routes>
<Route path="/" element={user ? <Home /> : <Navigate to="/register" replace />} />
.
.
.
</Routes>
</BrowserRouter>
)
.
.
.
Also you can see more detail in reactrouter docs:
https://reactrouter.com/docs/en/v6/getting-started/overview

routing problem: my routes on render are not working?

import Home from "./Pages/home/Home";
import TopBar from "./components/topbar/Topbar.jsx";
import Single from "./Pages/single/Single";
import Write from "./Pages/write/Write";
import Settings from "./Pages/settings/Settings";
import Login from "./Pages/login/Login";
import Register from "./Pages/register/Register";
import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom";
function App() {
const user = true;
return (
<Router>
<TopBar />
<Routes>
<Route exact path="/" component={Home} />
<Route path="/register" component={user ? <Home /> :{Register}} />
<Route path="/login" component={user ? <Home /> : {Login}} />
<Route path="/write" component={user ? <Write /> : {Register}} />
<Route path="/settings" component={user ? <Settings /> : {Register}} />
<Route path="/post/:Id" component={Single} />
</Routes>
</Router>
);
}
export default App;
This is my code but the homepage isnt rendering apart from topbar how do i resolve this. Am not sure if the syntax is correct.
Yeah, the syntax is a little mixed up. In react-router-dom version 6 the Route components render their components on the element prop as JSX, not on any component or render prop as a reference to a React component or function that returns JSX.
function App() {
const user = true;
return (
<Router>
<TopBar />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/register" element={user ? <Home /> : <Register />} />
<Route path="/login" element={user ? <Home /> : <Login />} />
<Route path="/write" element={user ? <Write /> : <Register />} />
<Route path="/settings" element={user ? <Settings /> : <Register />} />
<Route path="/post/:Id" element={<Single />} />
</Routes>
</Router>
);
}

React-Router how to prevent from redirect

So I have a problem in my code that when I refresh my page it sends me a NotFound page, but when I don't refresh the page still works while changing the route (single page application)
My routes code:
import React, { Component } from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import Navigation from './src/containers/Navigation/Navigation';
import PageProjects from './src/containers/PageProjects/PageProjects';
import NewPost from './src/components/pages/Projects/NewPost/NewPost'
import Home from './src/components/pages/Home/Home';
import Calendar from './src/components/pages/Calendar/Calendar';
import Team from './src/components/pages/Team/Team';
import Settings from './src/components/pages/Settings/Settings';
import NotFound from './src/components/pages/NotFound/NotFound';
class App extends Component {
render() {
return (
<div className="App" style={{ height: '100%' }}>
<BrowserRouter>
<div>
<Navigation />
<Switch>
<Route path="/profile" component={Home} exact />
<Route path="/projects" component={PageProjects} exact />
<Route path="/calendar" component={Calendar} exact />
<Route path="/team" component={Team} exact />
<Route path="/newpost" component={NewPost} exact />
<Route path="/settings" component={Settings} exact />
<Route path="*" component={NotFound} exact />
</Switch>
</div>
</BrowserRouter>
</div>
);
}
}
export default App;
Only my "/profile" page works because it's the page that I'm sending the index.html file from my route server
app.get('/profile', function(req, res){
res.sendFile(__basedir + "/react/index.html");
});
My Navigation Component:
import React, { Component } from 'react';
import {BrowserRouter, Route, Switch} from 'react-router-dom';
import Toolbar from '../../components/Toolbar/Toolbar';
import SideBar from '../../components/SideBar/SideBar';
import Backdrop from '../../components/Backdrop/Backdrop';
import Home from '../../components/pages/Home/Home';
import Calendar from '../../components/pages/Calendar/Calendar';
import Team from '../../components/pages/Team/Team';
import Settings from '../../components/pages/Settings/Settings';
import NotFound from '../../components/pages/NotFound/NotFound';
class Navigation extends Component {
state = {
sideBarOpen: false,
}
barToggleClickHandler = () => {
this.setState((prevState) => {
return{sideBarOpen: !prevState.sideBarOpen};
});
};
backdropClickHandler = () => {
this.setState({sideBarOpen: false});
};
render() {
let backdrop;
if(this.state.sideBarOpen){
backdrop = <Backdrop click={this.backdropClickHandler}/>;
}
return (
<section className="Navigation">
<Toolbar barClickHandler={this.barToggleClickHandler} />
<SideBar show={this.state.sideBarOpen}/>
{backdrop}
<main style={{marginTop: '150px'}}>
</main>
</section>
);
}
}
export default Navigation;
What can I do?
Thanks
(I'm using Reactjs, Nodejs, Express..)
app.get('/', function(req, res){
res.sendFile(__basedir + "/react/index.html");
});
or use hashrouter
<HashRouter>
<div>
<Navigation />
<Switch>
<Route path="/profile" component={Home} exact />
<Route path="/projects" component={PageProjects} exact />
<Route path="/calendar" component={Calendar} exact />
<Route path="/team" component={Team} exact />
<Route path="/newpost" component={NewPost} exact />
<Route path="/settings" component={Settings} exact />
<Route path="*" component={NotFound} exact />
</Switch>
</div>
</HashRouter>
This should do the trick !
app.get('/', function(req, res){
res.sendFile(__basedir + "/react/index.html");
});

Resources