React routers not working - It displays a blank page - javascript

Here is my App.js from my current project , I am facing an issue, whenever I render all my components individually which are mentioned in the commented part it gives me complete output, but as soon as I render it through the react-router-dom the page turns blank. Please help me with this.
import Topbar from "./components/topbar/Topbar";
import Homepage from "./pages/homepage/Homepage";
import Login from "./pages/login/Login";
import Register from "./pages/register/Register";
import Settings from "./pages/settings/Settings";
import Single from "./pages/single/Single";
import Write from "./pages/write/Write";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Header from "./components/header/Header";
import Posts from "./components/posts/Posts";
function App() {
const currentUser = true;
return (
// <>
// <Topbar/>
// <Header/>
// <Single/>
// <Homepage/>
// <Posts/>
// <Register/>
// <Login/>
// <Settings/>
// </>
<BrowserRouter>
<Topbar />
<Routes>
<Route exact path="/">
<Homepage />
</Route>
<Route path="/posts">
<Homepage />
</Route>
<Route path="/register">
{currentUser ? <Homepage /> : <Register />}
</Route>
<Route path="/login">{currentUser ? <Homepage /> : <Login />}</Route>
<Route path="/post/:id">
<Single />
</Route>
<Route path="/write">{currentUser ? <Write /> : <Login />}</Route>
<Route path="/settings">
{currentUser ? <Settings /> : <Login />}
</Route>
</Routes>
</BrowserRouter>
);
}
export default App;

Try changing your routes to look something like this:
<Route exact path="/" element={<Homepage />} />

The component you want to render should be in the element prop.
https://reactrouter.com/docs/en/v6/getting-started/overview
https://reactrouter.com/docs/en/v6/upgrading/v5
<Route exact path="/" element={<Homepage />} />
The only time you can put something inside a Route as a child element is for nested routing. For example:
<Route path="/teams" element={<Teams />}>
<Route path=":teams" element={<Team />} />
</Route>

I have been through this. I think you should install React Router first (Already installed it seems)
npm install react-router-dom#6
I suggest using it in the following way -
function App() {
return (
<Router>
<div className='container'>
<div className='Header'>
<h2>Blog Site</h2>
</div>
<div className='links'> // Mention your links here
<ul>
<li>
<Link to="/tag">Tags</Link>
</li>
<li>
<Link to="/startup">Startups</Link>
</li>
</ul>
</div>
<Routes> // Describe your routes here
<Route exact path="/tag" element={<Tag />} />
<Route exact path="/startup" element={<Startup />} />
</Routes>
</div>
</Router>
);
}
I have picked small code piece from my project, you can try using my approach.

Related

React error: No routes matched location "/"

My React app is giving me the error No routes matched location "/"
My App.js looks like:
import Form from './components/Form';
import NavMenu from './components/NavMenu';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
function App() {
// Irrelevant code
return (
<Router>
<div>
<NavMenu />
<Routes>
<Route path="/:nav_string" element={<Form />}></Route>
</Routes>
</div>
</Router>
);
}
export default App;
Any thoughts why this is happening?
I got rid of the error, although it's not a clean solution. I created a new component Home.js, added it to App.js with a route of "/" :
return (
<Router>
<div className="content">
<NavMenu response={response}/>
<Routes>
<Route path="/" element={<Home />}></Route> // Added home element
<Route path="/:nav_string" element={<Form response={response} />}></Route>
</Routes>
</div>
</Router>
);
Although I'm not a big fan of this solution because Home.js returns null. I just created it to get rid of this warning. What can someone do if they don't actually need a route with a path matching / ?
If you don't really need to render anything on the "/" path you could render a redirect to the form's route, perhaps with some default value.
Example:
return (
<Router>
<div className="content">
<NavMenu response={response} />
<Routes>
<Route path="/" element={<Navigate to="/someDefaultValue" replace />} />
<Route path="/:nav_string" element={<Form response={response} />} />
</Routes>
</div>
</Router>
);
An alternative could also be to render the Form component on both routes. RRD is optimized such that the Form component remains mounted while navigating between the routes or while the nav_string param value changes.
Example:
return (
<Router>
<div className="content">
<NavMenu response={response} />
<Routes>
<Route path="/" element={<Form response={response} />} />
<Route path="/:nav_string" element={<Form response={response} />} />
</Routes>
</div>
</Router>
);
Just make sure that Form can handle a potentially undefined nav_string param value. You could provide a fallback value.
const { nav_string = "someDefaultValue" } = useParams();
And then there is always the "catch all" route where you can render some fallback UI for any "unhandled" routes. This would include "/".
Example:
return (
<Router>
<div className="content">
<NavMenu response={response} />
<Routes>
<Route path="*" element={<NotFound />} />
<Route path="/:nav_string" element={<Form response={response} />} />
</Routes>
</div>
</Router>
);
You can add 404 route
Page not found will be displayed when no route matches the url
return (
<Router>
<div className="content">
<NavMenu response={response}/>
<Routes>
<Route path="/:nav_string" element={<Form response={response} />}></Route>
<Route path='*' element={<NotFound />} /> {/* You can change NotFound element*/}
</Routes>
</div>
</Router>
);
This should help:
<BrowserRouter>
<NavMenu/>
<Routes>
<Route path="/" element={<Form/>}></Route>
<Routes/>
<BrowserRouter/>
the format for "/:nav_string" is a path parameter, there is no "/" path
try type in for example "/Product", then it solved

React router hashhistory moving basename property before the hash [duplicate]

i want to use that Hashrouter, but when i try, i got this error:
<Router basename="/admin"> is not able to match the URL "/" because it does not start with the basename, so the <Router> won't render anything.
i put "Homepage": "./admin" in packedjson
but when i use BrowserRouter, its render normaly, can anyone explain why, please?
The code i'm using to try to understand router v6:
import "./styles.css";
import {
BrowserRouter,
Routes,
Route,
Navigate,
Outlet,
Link,
HashRouter,
} from "react-router-dom";
const ProtectedRoutes = () => <Outlet />;
const Configuration = () => <h1>Configuration</h1>;
const SummaryPage = () => <h1>SummaryPage</h1>;
const Dashboard = () => <h1>Dashboard</h1>;
const Appointments = () => <h1>Appointments</h1>;
const NotFound = () => <h1>NotFound</h1>;
export default function App() {
return (
<HashRouter basename="/admin">
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<Link to="/dashboard" className="link">
Home
</Link>
</div>
<Routes>
<Route path="/configuration/configure" element={<Configuration />} />
<Route path="/configuration" element={<SummaryPage />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/appointments" element={<Appointments />} />
<Route path="/" element={<Navigate replace to="/configuration" />} />
<Route path="*" element={<NotFound />} />
</Routes>
</HashRouter>
);
}
There mostly seems to be a misunderstanding with how the basename prop is applied in the router, specifically the HashRouter. With the HashRouter the basename prop is a value that is applied against the paths the app is handling, not against the domain path where the app is served/running.
Example:
<HashRouter basename="/admin">
<Link to="/dashboard" className="link"> // renders <a href="#/admin/dashboard">
Dashboard
</Link>
...
<Routes>
<Route path="/configuration">
<Route path="configure" element={<Configuration />} />
<Route index element={<SummaryPage />} />
</Route>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/appointments" element={<Appointments />} />
<Route path="/" element={<Navigate replace to="/configuration" />} />
<Route path="*" element={<NotFound />} />
</Routes>
</HashRouter>
In other words, the basename prop value is applied to the URL hash and not the URL path, i.e. it's applied to everything after the hash.
mysite.com/someSubdomain/#/admin /something / ... more nested paths
|--domain-|--subdomain--|#|--------------hash-----------------|
| | | |basename| app path | ... app subpaths
If you are wanting the "/admin" to show up prior to the hash, then this is part of where the entire app is deployed to and served up from. In this case the app needs to be deployed to mysite.com in a "/admin" subdirectory. You also won't need to specify the basename="/admin" if you don't want an additional "/admin" to show up in the app's routing.
mysite.com/admin/#/something
...
<HashRouter>
<Link to="/dashboard" className="link"> // renders <a href="#/dashboard">
Dashboard
</Link>
...
<Routes>
<Route path="/configuration">
<Route path="configure" element={<Configuration />} />
<Route index element={<SummaryPage />} />
</Route>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/appointments" element={<Appointments />} />
<Route path="/" element={<Navigate replace to="/configuration" />} />
<Route path="*" element={<NotFound />} />
</Routes>
</HashRouter>
update: Not a solution =[ basename not works in Routes, and hashrouter not working with basename
Some solution here:
https://github.com/remix-run/react-router/issues/7128#issuecomment-582591472
but i don't know if it's the best one.
// url where new router is created: https://my-site/who/users
const RootModule = () => {
return (
<main>
<BrowserRouter>
<Routes basename="who/users">
<nav>
<Link to="">Home</Link>
<Link to="who/users/about">About</Link>
<Link to="who/users/users">Users</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="who/users/about" element={<About />} />
<Route path="who/users/users" element={<Users />} />
</Routes>
</Routes>
</BrowserRouter>
</main>
);
};
and here working
SANDBOX

Navigate in react-router dom renders a blank page

I am a beginner with react-router-dom, there are two different states in the code when I dont use Navigate from react-router-dom , it works properly , but when I use the Navigate function it renders a blank page.
I have confirmed that all the individual components work and render properly.
Please help me solve this issue .
Here is my code of App.js without Navigate
import React from 'react';
import { Container } from '#material-ui/core';
import { BrowserRouter , Route , Routes , Navigate } from 'react-router-dom'
import PostDetails from './components/PostDetails/PostDetails';
import Home from './components/Home/Home';
import Navbar from './components/Navbar/Navbar';
import Auth from './components/Auth/Auth';
const App = () => {
const user = JSON.parse(localStorage.getItem('profile'));
return (
<BrowserRouter>
<Container maxWidth="lg">
<Navbar />
<Routes>
<Route exact path="/" element ={<Home/>} />
<Route path="/auth" element={<Auth/>} />
<Route path="/posts" exact element={<Home/>} />
<Route path="/posts/search" exact element={<Home/>} />
<Route path="/posts/:id" exact element={<PostDetails/>} />
<Route path="/auth" exact element={() => (!user ? <Auth /> : <Navigate to="/posts" />)} />
</Routes>
</Container>
</BrowserRouter>
)
};
export default App;
Here is my code of App.js with Navigate which does not works
import React from 'react';
import { Container } from '#material-ui/core';
import { BrowserRouter , Route , Routes , Navigate } from 'react-router-dom'
import PostDetails from './components/PostDetails/PostDetails';
import Home from './components/Home/Home';
import Navbar from './components/Navbar/Navbar';
import Auth from './components/Auth/Auth';
const App = () => {
const user = JSON.parse(localStorage.getItem('profile'));
return (
<BrowserRouter>
<Container maxWidth="lg">
<Navbar />
<Routes>
<Route path="/" exact component={() => <Navigate replace to="/posts" />} />
<Route path="/posts" exact element={<Home/>} />
<Route path="/posts/search" exact element={<Home/>} />
<Route path="/posts/:id" exact element={<PostDetails/>} />
<Route path="/auth" exact element={() => (!user ? <Auth /> : <Navigate replace to="/posts" />)} />
</Routes>
</Container>
</BrowserRouter>
)
};
export default App;
In react-router-dom#6 the Route components's element prop takes only a ReactNode, a.k.a. JSX. You've one route taking a component prop which is invalid, and two routes passing a function.
Use the element prop and pass JSX only.
Note that there is also no longer any exact prop, in RRDv6 all routes are always exactly matched.
<BrowserRouter>
<Container maxWidth="lg">
<Navbar />
<Routes>
<Route path="/" element={<Navigate replace to="/posts" />} />
<Route path="/posts" element={<Home />} />
<Route path="/posts/search" element={<Home />} />
<Route path="/posts/:id" element={<PostDetails />} />
<Route
path="/auth"
element={!user ? <Auth /> : <Navigate replace to="/posts" />}
/>
</Routes>
</Container>
</BrowserRouter>
If you are trying to protect these "/posts*" routes then it is common to create a layout route to handle redirecting to the login route or render the protected routes.
Example:
const AuthLayout = ({ authenticated }) =>
authenticated
? <Outlet />
: <Navigate to="/auth" replace />;
...
<BrowserRouter>
<Container maxWidth="lg">
<Navbar />
<Routes>
<Route element={<AuthLayout authenticated={!!user} />}>
<Route path="/posts" element={<Home />} />
<Route path="/posts/search" element={<Home />} />
<Route path="/posts/:id" element={<PostDetails />} />
</Route>
<Route path="/" element={<Navigate replace to="/posts" />} />
<Route
path="/auth"
element={!user ? <Auth /> : <Navigate replace to="/posts" />}
/>
</Routes>
</Container>
</BrowserRouter>
use element props instead component
<Route path="/" exact component={() => <Navigate replace to="/posts" />} />
<Route path="/" exact element={() => <Navigate replace to="/posts" />

React router rendering wrong page

i am developing an web app and I am new to react router. Evrything was going great until I found myself in need to render a whole new page, with new navbar and all.
that's my app.js
class App extends Component {
render() {
return (
<BrowserRouter>
<div className='App'>
<Layout>
<Header />
<NavigationB />
<Search />
<Switch> {/* to swtich to the desired path. Nest all route here */}
<Route path='/' component={Home} exact />
<Route path='/login' component={Login} />
<Route path='/register-choice' component={RegisterButton} />
<Route path='/register-patient' component={RegisterPatient} />
<Route path='/register-professional' component={RegisterProf} />
<Route path='/profesional-dashboard' component={ProfessionalDashboard} />
</Switch>
</Layout>
<Footer />
</div>
</BrowserRouter>
);
}
}
So, I wanted to go to /professional-dashboard but without rendenring all the components above such and Header, Search, etc.
I tried to go to my index.js file and set it up like this
ReactDOM.render(
<BrowserRouter>
<Switch> {/* to swtich to the desired path. Nest all route here */}
<Route path='/' component={App} exact />
<Route path='/professional-dashboard' component=
{ProfessionalDashboard} />
</Switch>
</BrowserRouter>,
document.getElementById('root'));
The idea was, in my form whenever I press register, it should send me to the dashboard of the professional.
At the end of my Register.js file you would find
const WrappedRegistrationForm = Form.create()(RegisterProf);
ReactDOM.render(
<BrowserRouter>
<div>
<WrappedRegistrationForm />
</div>
</BrowserRouter>
, document.getElementById('root'));
export default WrappedRegistrationForm;
I am using Ant Design, so the form renders WrappedRegistrationForm. At first it was not working then I wrapped it around BrowserRouter, I don't get the error anymore, but now when I press the register button, it takes me to /professional-dashboard but it loads app.js and not ProfessionalDashboard.js
Funny thing is, if I refresh the page, it loads ProfessionalDashboard.js normally.
Hope I'm explaining myself well.
Glad if you can help me!!
Hi could try something like this rendering the top one first if its a match if not it will go on to render the rest of the app :) hope this is clear
class App extends Component {
render() {
return (
<BrowserRouter>
<Switch>
<Route exact path='/profesional-dashboard' component={ProfessionalDashboard} />
<StandarRoute path='/' component={MainPage} />
<Switch />
</BrowserRouter>
);
}
}
class MainPage extends Component {
render(){
return(
<div className='App'>
<Layout>
<Header />
<NavigationB />
<Search />
<Switch> {
<Route path='/' component={Home} exact />
<Route path='/login' component={Login} />
<Route path='/register-choice' component={RegisterButton} />
<Route path='/register-patient' component={RegisterPatient} />
<Route path='/register-professional' component={RegisterProf} />
</Switch>
</Layout>
<Footer />
</div>
)
}
}
Try including "exact" before component in your Route, or including "exact" before the 'To' in your Link
Try,
<Route exact path="/register" render={() => ( <Redirect to="/dashboard"/>)
Why do you render two times with reactDOM by the way? That might be what’s causing the issue too. Just exporting it and putting it in route component should suffice.

How to hide navbar in login page in react router

I want to hide the navbar in a login page.
I did it actually, but I can't see the navbar on other pages.
This code is part of My App.jsx file.
I make history in App's state. And I hide navbar, when this pathname is '/' or '/login'.
It works!
But then I typed the ID and password, and clicked the login button, got 'success' result, and navigated to '/main'.
Now I can't see navbar in main component too.
How can I do this?
Sorry about my short english. If you can't understand my question, you can comment.
constructor(props) {
super(props);
this.state = {
isAlertOpen: false,
history: createBrowserHistory(),
};
this.toggleAlert = this.toggleAlert.bind(this);
}
<BrowserRouter>
<div className="App">
{this.state.history.location.pathname === '/' || this.state.history.location.pathname === '/login' ? null
: <Header toggleAlert={this.toggleAlert} />}
<div className="container">
{this.state.history.location.pathname === '/' || this.state.history.location.pathname === '/login' ? null
: <Navbar />}
<Route exact path="/" render={() => <Redirect to="/login" />} />
<Route path="/login" component={Login} />
<Route path="/main" component={Main} />
<Route path="/user" component={User} />
<Route path="/hw-setting" component={Setting} />
<Route path="/hw-detail/:id" component={HwDetail} />
<Route path="/gas-detail/:id" component={GasDetail} />
{this.state.isAlertOpen ? <Alert /> : null}
</div>
</div>
</BrowserRouter>
login(event) {
event.preventDefault();
userService.login(this.state.id, this.state.password).subscribe(res => {
if (res.result === 'success') {
global.token = res.token;
this.props.history.push('/main');
} else {
alert(`[ERROR CODE : ${res.statusCode}] ${res.msg}`);
}
});
You could structure your Routes differently so that the Login component doesn't have the Header Like
<BrowserRouter>
<Switch>
<div className="App">
<Route exact path="/(login)" component={LoginContainer}/>
<Route component={DefaultContainer}/>
</div>
</Switch>
</BrowserRouter>
const LoginContainer = () => (
<div className="container">
<Route exact path="/" render={() => <Redirect to="/login" />} />
<Route path="/login" component={Login} />
</div>
)
const DefaultContainer = () => (
<div>
<Header toggleAlert={this.toggleAlert} />
<div className="container">
<Navbar />
<Route path="/main" component={Main} />
<Route path="/user" component={User} />
<Route path="/hw-setting" component={Setting} />
<Route path="/hw-detail/:id" component={HwDetail} />
<Route path="/gas-detail/:id" component={GasDetail} />
{this.state.isAlertOpen ? <Alert /> : null}
</div>
</div>
)
As of the latest release of React Router v6, it is no longer possible to pass a <div> component inside the Routes (v6) aka Switch(v5 or lower) to render a Navbar. You will need to do something like this:
Create two Layout components. One simply renders a Nav and the other one does not. Suppose we name them
<WithNav />
<WithoutNav />
You will need to import <Outlet /> from the React router and render inside the Layout components for the routes to be matched.
Then in your App or where ever you have your Router you will render like below ....
// WithNav.js (Stand-alone Functional Component)
import React from 'react';
import NavBar from 'your navbar location';
import { Outlet } from 'react-router';
export default () => {
return (
<>
<NavBar />
<Outlet />
</>
);
};
// WithoutNav.js (Stand-alone Functional Component)
import React from 'react';
import { Outlet } from 'react-router';
export default () => <Outlet />
// your router (Assuming this resides in your App.js)
<Routes>
<Route element={<WithoutNav />}>
<Route path="/login" element={<LoginPage />} />
</Route>
<Route element={<WithNav />}>
<Route path="/=example" element={<Example />} />
</Route>
</Routes>
LoginPage will not have a nav however, Example page will
Simplest way is use div tag and put components in which you want navbar and put login route component outside div tag:
<div className="App">
<Router>
<Switch>
<Route exact path="/" component={Login} />
<div>
<NavBar />
<Route exact path="/addproduct" component={Addproduct}></Route>
<Route exact path="/products" component={Products}></Route>
</div>
</Switch>
</Router>
</div>
Put the Route with path="/" below every other routes :
<Switch>
<Route path="/login" component={Login} />
<Route path="/" component={Home} />
</Switch>
It will work.
I'm was trying to solve this problem, what i did was add component helmet, to install it use : yarn add react-helmet --save.
import {Helmet} from 'react-helmet';
<Helmet>
<script src="https://kit.fontawesome.com/.....js" crossorigin="anonymous"></script>
</Helmet>
The accepted answer has problem if you need to add other default route within the switch if no other route matches, e.g., 404 page, not found page.
I ended up using simple css to hide navigation bar inside my login page.
class LoginPage extends React.Component<>{
...
// Hide navigation bar in login page. Do it inside ComponentDidMount as we need to wait for navbar to render before hiding it.
componentDidMount(){
document.getElementById('navigation-bar')!.style.display = "none";
}
componentWillUnmount(){
document.getElementById('navigation-bar')!.style.display = "flex";
}
render(){
return(
// your login/signup component here
...
)
}
}

Categories