I'm creating a website, and I want the users to be directed to a specific page when they open the site. The page they are going to be directed to depends on if they already logged in. My problem is: the router doesn't work (user is not redirected to any page) and all that appears is a blank page. I've tried to get rid of the routes, but even though, I couldn't display anything on the index page. Maybe the problem is not even the router, but something else.
I never get any error messages. Here are the parts of the code, where I think the problem may be.
_app.js:
import React from 'react'
import { BrowserRouter as Router, Route } from "react-router-dom"
import Novidades from './lancamento'
import SignUp from './signup'
import Croosa from './croosa'
import { AuthProvider } from '../utils/auth'
import PrivateRoute from '../utils/PrivateRoute'
const App = () => {
return(
<AuthProvider>
<Router>
<div>
<PrivateRoute exact path='/lancamento' component={Lancamento} />
<Route exact path='/croosa' component={Croosa}/>
<Route exact path='/signup' component={SignUp} />
</div>
</Router>
</AuthProvider>
)
}
export default App
index.js:
import React from 'react'
import App from './_app'
export default function Home() {
return(
<App/>
)
}
And the PrivateRoute.js, which decides to which page the user is going to be redirected:
import React, { useContext } from "react";
import { Route, Redirect } from "react-router-dom";
import { AuthContext } from "./auth";
const PrivateRoute = ({ component: RouteComponent, ...rest }) => {
const {currentUser} = useContext(AuthContext);
return (
<Route
{...rest}
render={routeProps =>
!!currentUser ? (
<RouteComponent {...routeProps} />
) : (
<Redirect to={"/signup"} />
)
}
/>
)
}
export default PrivateRoute
I would appreciate it if someone could point out my mistake(s).
Next.js uses a filesystem based routing structure.
You have a misunderstanding of how the _app.js file works. It's the parent component that is responsible for rendering the other components that get exported from other pages.
For example: if my _app.js file looks like this:
export default function App({ Component, pageProps }) {
return (
<div>
<p>This was injected by _app.js</p>
<Component {...pageProps} />
<div>
);
}
and my pages/index.js file looks like this:
export default function Hello(){
return <h1>Hello World!</h1>
}
With that setup if I visit the localhost:3000/ then the following will get rendered
<div>
<p>This was injected by _app.js</p>
<h1>Hello World!</h1>
</div>
What you did instead is in your _app.js you ignored the Component property that was passed and so on every page you visit the same content will be rendered. That is:
<AuthProvider>
<Router>
<div>
<PrivateRoute exact path="/lancamento" component={Lancamento} />
<Route exact path="/croosa" component={Croosa} />
<Route exact path="/signup" component={SignUp} />
</div>
</Router>
</AuthProvider>
The reason your index page is blank is because you didn't set up a route for / and so no component will be rendered by react router on that page. Regardless I suggest you stop using react router and start using the built in routing system with next.js
I've following issue with my ionic react app.
After initial launch the Login page appears as expected.
After successful login, this.state.login.status turns true and the Home component gets loaded (seeing log output of this component). But the screen only shows a blank page.
After reloading the page (with successful login data; I'm saving this in localStorage), the Home component appears as expected.
This behaviour is the same on every device (Chrome, Android, Ios). And the console doesn't show any error message.
I only saw one difference between Android and Chrome. If I logout with chrome, the Login page appears and I can relog (without the blank page). So the issue is only for the first state change.
If I'm using my android app (built with Capacitor), the blank page appears on every state change and I have to restart the app, after every login/logout.
Does anyone have an idea what could cause this behaviour? I already searched for similar problems, but nothing of them worked. For instance changing the homepage to '.' in package.json.
App.tsx:
import React from 'react';
import { Redirect, Route } from 'react-router-dom';
import { IonApp, IonRouterOutlet } from '#ionic/react';
import { IonReactRouter } from '#ionic/react-router';
import Home from './pages/Home';
import Login from './pages/Login';
import Xxx from './util/Xxx';
/* Core CSS required for Ionic components to work properly */
import '#ionic/react/css/core.css';
/* Basic CSS for apps built with Ionic */
import '#ionic/react/css/normalize.css';
import '#ionic/react/css/structure.css';
import '#ionic/react/css/typography.css';
/* Optional CSS utils that can be commented out */
import '#ionic/react/css/padding.css';
import '#ionic/react/css/float-elements.css';
import '#ionic/react/css/text-alignment.css';
import '#ionic/react/css/text-transformation.css';
import '#ionic/react/css/flex-utils.css';
import '#ionic/react/css/display.css';
/* Theme variables */
import './theme/variables.css';
interface AppProps {};
interface AppState {
isSignedIn: boolean,
user: string
};
class App extends React.Component<AppProps, AppState> {
constructor(props: AppProps) {
super(props);
const login = Xxx.isSignedIn();
this.state = {
isSignedIn: login.status,
user: login.user
};
this.checkLogin = this.checkLogin.bind(this);
}
checkLogin() {
const login = Xxx.isSignedIn();
this.setState({
isSignedIn: login.status,
user: login.user
});
}
render() {
return (
<IonApp>
<IonReactRouter>
<IonRouterOutlet>
<Route
path="/home"
exact={true}
render={
props => {
return this.state.isSignedIn ?
<Home {...props} user={this.state.user} checkLogin={this.checkLogin}/> :
<Login checkLogin={this.checkLogin}/>;
}
}
/>
<Route exact path="/" render={() => <Redirect to="/home" />} />
</IonRouterOutlet>
</IonReactRouter>
</IonApp>
);
}
};
export default App;
Could you try this ?
I think it's because the virtual dom do not change...
if (!this.state.isSignedIn) {
return <Login checkLogin={this.checkLogin}/>
}
return (
<IonApp>
<IonReactRouter>
<IonRouterOutlet>
<Route
path="/home"
exact={true}
render={
props => <Home {...props} user={this.state.user} checkLogin={this.checkLogin}/>
}
}
/>
<Route exact path="/" render={() => <Redirect to="/home" />} />
</IonRouterOutlet>
</IonReactRouter>
</IonApp>
);
look at using React.Context to create an context for managing the application state, then you dont need to be passing the state all over the place with properties
const App: React.FC = () => {
const { authCtx } = React.useContext(AppContext);
return (
<IonApp>
{authCtx.authenticated ? (
<IonReactRouter>
<IonSplitPane contentId="main">
<Menu />
<IonRouterOutlet id="main">
<Route path="/page/:name" component={Page} exact />
<Redirect from="/" to="/page/Inbox" exact />
</IonRouterOutlet>
</IonSplitPane>
}
</IonReactRouter>
) : (
<IonReactRouter>
<Route path="/auth/login" component={LoginPage} exact />
<Route
path="/auth/create-account"
component={CreateAccountPage}
exact
/>
<Redirect from="/" to="/auth/login" exact />
</IonReactRouter>
)}
</IonApp>
);
};
IN index.ts
import { AuthProvider } from "./helpers/my-context";
ReactDOM.render(
<AuthProvider>
<App />
</AuthProvider>,
document.getElementById("root")
);
In my-context.ts
import React from "react";
// create the context
export const Context = React.createContext<any>(undefined);
// create the context provider, we are using use state to ensure that
// we get reactive values from the context...
export const AuthProvider: React.FC = ({ children }) => {
// the reactive values
const [authCtx, setAuthCtx] = React.useState({
authenticated: null,
user: null,
});
// the store object
let state = {
authCtx,
setAuthCtx,
};
// wrap the application in the provider with the initialized context
return <Context.Provider value={state}>{children}</Context.Provider>;
};
export default Context;
I'am nesting routes in my project. I have App.js in which I have defined the routes and inside the component I have more routes which I want them to be nested. The only problem is that my nested route is in the component which is connected to redux. The nested routing is not working properly.
I have already tried it from the official documentation but it does not work.
https://reacttraining.com/react-router/core/guides/philosophy
App.js
import { connect } from "react-redux";
import { withRouter, Route } from "react-router-dom";
function HowItWorks() {
return (
<div>
<h2 style={{ margin: 20 }}>How It Works</h2>
</div>
);
}
function AboutUs() {
return (
<div>
<h2 style={{ margin: 20 }}>About Us</h2>
</div>
);
}
class App extends React.Component {
render() {
return (
<div>
<Route path="/" exact component={HowItWorks} />
<Route path="/howitworks" exact component={HowItWorks} />
<Route path="/aboutus" component={AboutUs} />
<Route path="/admin" component={AdminContainer} />
</div>
);
}
}
Below is my Redux Container file which gets called based on the route specified in App.js. Also my App.js file may get connected to redux in the future by the connect() method.
AdminContainer.js
import { connect } from "react-redux";
import MainDesktopComponent from "../components/Admin/MainDesktopComponent";
const mapStateToProps = state => ({});
const mapDispatchToProps = dispatch => {
return {};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(MainDesktopComponent);
MainDesktopComponent.js
I have tried this i.e giving the nested route inside Switch and many different ways but it is not working. Also note that I also want to pass props to the Dashboard component which will come from the above redux container component through mapstatetoprops.
import React from "react";
import Dashboard from "./Dashboard";
import { Route } from "react-router-dom";
import { Switch } from "react-router";
function MainDesktopComponent(props) {
return (
<div>
<Switch>
<Route
exact
path="/admin/dashboard"
render={props => {
<Dashboard/>;
}}
/>
</Switch>
</div>
);
}
export default MainDesktopComponent;
I'm not sure but what about try this?
<Switch>
<Route
exact
path="/admin/dashboard"
render={cProps => <Dashboard {...cProps} {...props} />}
/>
</Switch>
return Route render component.
I am trying to route but it is not working it shows a blank page
here is the code
when I hit localhost:3000/home it is not showing anything
import React, { Component } from 'react';
import { BrowserRouter as Router, Route } from "react-router-dom";
const Home = () =>{
return(
<div>
<p>Home</p>
</div>
);
}
class App extends Component {
render() {
return (
<Router>
<Route path='/home' Component={Home}/>
</Router>
);
}
}
export default App;
component prop in <Route /> is case-sensitive, make it lower case
class App extends Component {
render() {
return (
<Router>
<Route path='/home' component={Home}/>
</Router>
);
}
How to implement conditional routing i.e. if and only if some conditions satisfies, then routing should occur.
For example, if and only if the user enters the correct credentials, login should be successful and the user should be able to see the welcome page.
If we directly hit some URL like localhost:8080/welcome, that should not be navigated to welcome page. The welcome page should only be displayed after login.
How to achieve this, can anyone help me please?
App.js
import React, { Component } from 'react';
import Header from './Header';
class App extends Component{
render(){
return(
<div>
<Header />
</div>
);
}
}
export default App;
Header.js
import React, { Component } from 'react';
import {Link} from 'react-router-dom';
import Login from './Login';
import SignUp from './SignUp';
class Header extends Component{
render(){
return(
<div>
<nav class="navbar navbar-default">
<div class="container-fluid">
<ul class="nav navbar-nav">
<li><Link to={Login}>Login</Link></li>
<li><Link to={Login}>SignUp</Link></li>
</ul>
</div>
</nav>
</div>
);
}
}
export default Header;
AllRoutes.js
import React, { Component } from 'react';
import { Switch, Route } from 'react-router-dom';
import Login from './Login';
import SignUp from './SignUp';
import Welcome from './Welcome';
class AllRoutes extends Component{
render(){
return(
<Switch>
<Route exact path="/login" component={Login} />
<Route exact path="/signup" component={SignUp} />
<Route exact path="/Welcome" component={Welcome} />
</Switch>
);
}
}
export default AllRoutes;
Welcome.js
import React, { Component } from 'react';
class Welcome extends Component{
render(){
return(
<div>
<h2>Welcome to MainPage..</h2>
</div>
);
}
}
export default Welcome;
To help answer your question, I think you may need to also ask how that route should get blocked. Looking through the example above, you don't yet have a mechanism that helps answer the question of "should I be able to visit this page". That might come from state, redux, or some other means of determining if the user is logged in.
Since react-router is just plain React (one of my favorite parts!!) you have all the tools available to you that you would to conditionally show any part of your React app.
Here are a couple examples of how you might achieve this (by no means is this exhaustive. Be creative! It all depends on your requirements and the tools you are using)
class AllRoutes extends Component{
render(){
return(
<Switch>
<Route exact path="/login" component={Login} />
<Route exact path="/signup" component={SignUp} />
{ this.state.authenticated &&
<Route exact path="/Welcome" component={Welcome} />
}
</Switch>
);
}
}
One of my favorite ways to accomplish this is creating a ProtectedRoute component
class ProtectedRoute extends Component {
render() {
const { component: Component, ...props } = this.props
return (
<Route
{...props}
render={props => (
this.state.authenticated ?
<Component {...props} /> :
<Redirect to='/login' />
)}
/>
)
}
}
class AllRoutes extends Component {
render() {
return (
<Switch>
<Route path='/login' component={Login} />
<ProtectedRoute path='/welcome' component={Welcome} />
</Switch>
)
}
}
While I didn't include any specific logic to how state.authenticated was set, this may come from anywhere (by no means does it needs to come from state). Do your best to answer the question of "how do I determine whether a user is authenticated" and use that mechanism as the means to handle route authentication.
For that you need to break the entire app into two parts, normally accessible and protected part. Protected part will be accessible only after successful login.
To achieve that functionality, create a wrapper of protected part, and define its routes with path='/', and put the condition inside that. All the protected routes should be defined inside that wrapper component. If anyone try to access those routes without login, wrapper will redirect them to login page.
Like this:
class AllRoutes extends Component{
render(){
return(
<Switch>
<Route exact path="/login" component={Login} />
<Route exact path="/signup" component={SignUp} />
<Route path="/" component={AppWrapper} />
</Switch>
);
}
}
AppWrapper Component (assuming you are using some way to maintain whether user is logged-in or not, so put the proper check in if condition):
import { Redirect } from 'react-router-dom'
class AppWrapper extends Component{
render(){
if(/*not login*/)
return <Redirect to="/login" />
return(
<div>
App wrapper
<Route path='/Welcome' component={Welcome} />
</div>
);
}
}
I would like to join the party with simple solution.
Just conditional render in the component prop in as follows:
<Router>
<Navigation />
<Switch>
<Route
exact
path="/"
component={
loading
? () => <div>Loading posts...</div>
: () => <Home posts={posts} />
}
/>
<Route path="/login" component={Login} />
</Switch>
</Router>
Here i am trying to fetch some data from an api when it fetched (loading) should be false and renders Home component.
You can do something like:
let redirectToUrl;
if ( not logged in ) //check condition
{
redirectToUrl = <Redirect to={loginPage}/>;
}
and use the same:
<Router>
<div>
{redirectToUrl}
<Switch>
<Route />
</switch>
</div>
</Router>
For the same you need to import from react-router-dom:
import {
BrowserRouter as Router,
Route,
browserHistory,
Redirect,
Link,
Switch
} from "react-router-dom";
Best way is to create a HOC.
Considering you are maintaining auth state in your redux store. Or else you can check with your own variable.
Create requireAuth.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
export default function(ComposedComponent) {
class Authentication extends Component {
static contextTypes = {
router: React.PropTypes.object
}
componentWillMount() {
if (!this.props.authenticated) {
this.context.router.push('/');
}
}
componentWillUpdate(nextProps) {
if (!nextProps.authenticated) {
this.context.router.push('/');
}
}
render() {
return <ComposedComponent {...this.props} />
}
}
function mapStateToProps(state) {
return { authenticated: state.auth.authenticated };
}
return connect(mapStateToProps)(Authentication);
}
Now in the routes you can use this hoc and pass the component.
import RequireAuth from './requireAuth';
...
<Route exact path="/Welcome" component={RequireAuth(Welcome)} />
The best and simple thing you can do is to create a state variable login and route based on the boolean values. the logic to set is up to you. i can show an example of simple routing based on condition. I store my pages in a array and use the map function to switch to different routes. For an example I have inserted my DesignerHome.js for your reference
This is my App.js
import React,{Component} from 'react';
import{BrowserRouter as Router,Switch,Route,Redirect,} from 'react-router-dom'
import MainHome from './MainHome'
import DesignerHome from './designer/DesignerHome'
export default class App extends Component{
constructor(){
super()
this.state={
login : true,
r_page :[
{
path :'/designerhome',
component : DesignerHome,
},]
}
}
render(){
return(
<Router>
<Switch >
<Route path='/' exact component={MainHome}/>
{this.state.r_page.map((item , i)=>(this.state.login?
<Route exact {...item}/> : <Redirect to="/" /> ))}
</Switch>
</Router>
)
}
}
This is my DesignerHome.js
import React,{Component} from 'react';
export default class DesignerHome extends Component{
render(){
return(
<div>
designer home
</div>
)
}
}
create a state for authentication. based on that navigate to the page.
Also I used render instead of component in Route.
import React, { Fragment, useState, useEffect } from "react";
import Dashboard from "./components/Dashboard";
import Login from "./components/Login";
import Register from "./components/Register";
import {
BrowserRouter as Router,
Switch,
Route,
Redirect,
} from "react-router-dom";
function App() {
const [isAuthenticated, setIsAuthenticated] = useState(false);
const setAuth = (boolean) => {
setIsAuthenticated(boolean);
};
useEffect(() => {
isAuth(); // to be implemented
}, []);
return (
<Fragment>
<Router>
<div className="container">
<NavigationCard />
<Switch>
<Route
exact
path="/login"
render={(props) =>
!isAuthenticated ? (
<Login {...props} setAuth={setAuth} />
) : (
<Redirect to="/dashboard" />
)
}
/>
<Route
exact
path="/register"
render={(props) =>
!isAuthenticated ? (
<Register {...props} setAuth={setAuth} />
) : (
<Redirect to="/login" />
)
}
/>
<Route
exact
path="/dashboard"
render={(props) =>
isAuthenticated ? (
<Dashboard {...props} setAuth={setAuth} />
) : (
<Redirect to="/login" />
)
}
/>
</Switch>
</div>
</Router>
</Fragment>
);
}
export default App;