I have code as below. I want Navigation component to appear on Home and About page, but not in Contact. How can I do that ?
import React, { Component } from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import Home from './components/Home';
import About from './components/About';
import Contact from './components/Contact';
import Error from './components/Error';
import Navigation from './components/Navigation';
class App extends Component {
render() {
return (
<BrowserRouter>
<div>
<Navigation />
<Switch>
<Route path="/" component={Home} exact/>
<Route path="/about" component={About}/>
<Route path="/contact" component={Contact}/>
</Switch>
</div>
</BrowserRouter>
);
}
}
export default App;
Just add a condition to check if your route is contact or not and don't render the content of Navigation by returning null. You can get the url using window.location.
I am new to React and practicing with an online website for repairing appliances. I have used react-router and created all my routes in a separate file.
I have a problem though, I can open any link from the address bar like:
http://localhost:3000/<randomword>
I only want routes to be opened that I have declared in my routes component while if I type http://localhost:3000/something, I get an empty page with my header and footer in it.
here are my codes:
Index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from "react-router-dom";
import Routes from './Routes';
import './index.css';
const App = () => {
return(
<BrowserRouter>
<Routes />
</BrowserRouter>
)
}
ReactDOM.render(<App/>,document.getElementById('root'));
App.js:
import React, {Component} from 'react';
import { Route, BrowserRouter } from 'react-router-dom';
import Layout from './Containers/Layout';
import LandingPage from './Containers/Pages/LandingPage';
import About from './Containers/Pages/About';
import Cities from './Containers/Pages/Cities';
import Discount from './Containers/Pages/Discount';
class Routes extends Component {
render(){
return (
<div>
<Layout>
<BrowserRouter>
<Route path="/" render={props => <LandingPage {...props} />} exact component={LandingPage}/>
<Route path="/About" component={About}/>
<Route path="/Cities" component={Cities}/>
<Route path="/Discount" component={Discount}/>
</BrowserRouter>
</Layout>
</div>
);
}
};
export default Routes;
Layout.js:
import React, { Component } from 'react';
import Header from "./Layouts/Header";
import Footer from './Layouts/Footer';
import './Layout.css';
export default class Layout extends Component {
constructor(){
super();
this.state= {
}
}
render() {
return (
<div className="page-container">
<Header/>
<div className="content-wrap">
{this.props.children}
</div>
<Footer/>
</div>);
}
}
Can someone help me figure out how I should stop random random pages to be opened from addressbar?
Just want to start by saying I'm completely self-taught with React so I apologize if this answer is incorrect. However, in my experience with react-router I always have a Switch inside of my BrowserRouter. So your Routes class in app.js should something like this:
class Routes extends Component {
render(){
return (
<div>
<Layout>
<BrowserRouter>
<Switch>
<Route path="/" render={props => <LandingPage {...props} />} exact component={LandingPage}/>
<Route path="/About" component={About}/>
<Route path="/Cities" component={Cities}/>
<Route path="/Discount" component={Discount}/>
</Switch>
</BrowserRouter>
</Layout>
</div>
);
}
};
Just be sure you don't forget to update your imports to
import { Switch, Route, BrowserRouter } from 'react-router-dom';
import { Redirect } from "react-router-dom"
<Route path="/not-found" component={notFound-Component} />
<Redirect to="/not-found" />
This will always redirect you to 404 component if route is not present just make a 404 component and u should add the redirect at the end after all routes are defined
My react component should work as follows:
Check a global variable for error and if there is error redirect to home and unset the global error variable.
Otherwise it should render a which will use current page's location to redirect to correct location.
How should I go about doing this. The only way which somehow works is if I do conditional render and set global variable in render. Is there any better way?
In this example I'm using context api to share the state across all routes available.
For question No. 1 - use protected route. (Much simpler & neat)
predeclared path & component on <ProtectedRoute path="/anyPath" component={anyComponent}/>
if you want to have flexibility on setting the path yourself, then go to methods No. 2 below
in App.js:-
import React from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import { ErrorState } from "./contexts/ErrorState";
// import ProtectedRoute from "./comps/routes/ProtectedRoute";
import ProtectedRouteCustom from "./comps/routes/ProtectedRouteCustom";
import Home from "./comps/Home";
import Demo from "./comps/Demo";
import Dashboard from "./comps/Dashboard";
import "./style.css";
export default function App() {
return (
<ErrorState>
<Router>
<NavBar />
<Switch>
<Route exact path="/" component={Home} />
<Demo exact path="/demo" component={Demo} />
{/*} <ProtectedRoute exact path="/demo/dashboard" component={Dashboard} /> */}
<ProtectedRouteCustom path="/demo" />
<Route path="*" component={() => "Not Found"} />
</Switch>
</Router>
</ErrorState>
);
}
ProtectedRoute.js (emphasis more on Route render):-
import React from "react";
import { Redirect, Route } from "react-router-dom";
import { useError } from "../../contexts/ErrorState";
const ProtectedRoute = ({ component: Component, ...rest }) => {
const [errorState, errorDispatch] = useError();
const { error } = errorState;
return (
<Route
{...rest}
render={props => {
// you can use props.location.pathname to redirect user to the route path you have specified in App.js (see in console.log)
console.log(props);
// render Dashboard component if 'error' === false
if (!error) return <Component {...props} />;
// redirect to homepage if error === false
else
return (
<Redirect
to={{
// specify the path to redirect (if condition 'error' === true)
pathname: "/",
state: { from: props.location }
}}
/>
);
}}
/>
);
};
export default ProtectedRoute;
For question No. 2 - you can build your own custom protected route
path can be specified or set it yourself in ProtectedRouteCustom
App.js:-
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import { ErrorState } from "./contexts/ErrorState";
// import ProtectedRoute from "./comps/routes/ProtectedRoute";
import ProtectedRouteCustom from "./comps/routes/ProtectedRouteCustom";
import Home from "./comps/Home";
import Demo from "./comps/Demo";
import Dashboard from "./comps/Dashboard";
import "./style.css";
export default function App() {
return (
<ErrorState>
<Router>
<NavBar />
<Switch>
<Route exact path="/" component={Home} />
<Demo exact path="/demo" component={Demo} />
{/*} <ProtectedRoute exact path="/demo/dashboard" component={Dashboard} /> */}
<ProtectedRouteCustom path="/demo" />
<Route path="*" component={() => "Not Found"} />
</Switch>
</Router>
</ErrorState>
);
}
custom protected route:- (emphasis more on Redirect rather than Route render)
import React from "react";
import { Redirect, Route } from "react-router-dom";
import { useError } from "../../contexts/ErrorState";
import Dashboard from "../Dashboard";
const ProtectedRouteCustom = ({ path }) => {
const [errorState, errorDispatch] = useError();
const { error } = errorState;
return (
<>
{error ? (
<Redirect to="/" />
) : (
<>
<Redirect from={path} to={path + "/dashboard"} />
<Route to={path + "/dashboard"} component={Dashboard} />
</>
)}
</>
);
};
export default ProtectedRouteCustom;
You can see the sandbox here for full working code.
Guidelines on how to use the sandbox code
Environment for No. 1:-
uncomment/enable:
import ProtectedRoute from "./comps/routes/ProtectedRoute";
<ProtectedRoute exact path="/demo/dashboard" component={Dashboard} />
comment/disable:
import ProtectedRouteCondition from "./comps/routes/ProtectedRouteCondition";
<ProtectedRouteCondition path="/demo" />
Environment for No. 2: run as it is
Generally all coder using your methods. If you checking React in Facebook Group. You can find correct answer ı think.
I am having problems dividing my application and using several routers. I have a main router where it handles several small applications and in each mini application I want to manage its opportune routes. What am I failing?
What I want to do is when I receive the data of the request, redirect me to a new screen but I can not get it. Can anybody help me? Thank you
Example https://stackblitz.com/edit/react-c2tkgf?file=Hello.js
Routes.js
import { BrowserRouter } from 'react-router-dom'
import React from 'react'
import { Switch, Route } from 'react-router-dom'
import { AuthenticatedRoute } from 'components/authenticated-route'
import Clients from 'components/clients'
import { Login } from 'components/login'
import Home from './Home/Home'
const Routes = () => {
return (
<BrowserRouter>
<Switch>
<Route exact path="/" component={Home} />} />
<Route exact path="/clients" component={Clients} />
<Route exact path="/login" component={Login} />} />
</Switch>
</BrowserRouter>
)
}
export default Routes
Clients.js
import React, { Component } from 'react'
import { connect } from 'react-redux'
import Dashboard from './Dashboard/Dashboard'
import { Redirect, Route, Switch } from 'react-router-dom'
class Clients extends Component {
render() {
return (
<div>
<SearchCustomers />
{this.props.customer.token ? (
<div>
<Switch>
<Route path={`/clients:${this.props.customer.id}/dashboard`} component={Dashboard} />
</Switch>
<Redirect to={`/clients:${this.props.customer.id}/dashboard`} />
</div>
) : null}
</div>
)
}
}
const mapStateToProps = state => {
return {
customer: state.customer,
}
}
export default connect(mapStateToProps)(Clients)
In your Routes component you have:
<Route exact path="/clients" component={Clients} />
<Route exact path="/login" component={Login} />} />
since you have exact on there, those components will only be rendered when at exactly /clients or /login. in your built components, once you change the path, your parent component no longer renders, therefore nothing inside those components will render. remove the exact from your Routes:
<Rout path="/clients" component={Clients} />
<Rout path="/login" component={Login} />} />
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;