I have been unable to hide the sidebar and Navbar for some components which include login, signup, forget-password and reset-password confirm-verification
i have tried almost every everyone available to me using the stackoverflow, but none was able to work for me including [blog]:https://medium.com/#sandip21/how-to-hide-navbar-footer-on-authentication-pages-in-reactjs-40714ee1ce48, yet i couldn't get it to work
here is my app.js code
import React from 'react';
import {BrowserRouter as Router, Route, Switch} from 'react-router-dom';
import {withRouter} from 'react-router-dom'
import Header from './component/layout/Header';
import Sidebar from './component/layout/Sidebar';
import Shipped from './component/pages/Shipped';
import Warehouse from './component/pages/Warehouse';
import Assisted from './component/pages/Assisted';
import Login from './component/auth/Login'
import Reset from './component/auth/Resetpass'
import ConfirmEmail from './component/auth/ConfirmEmail'
import Signup from './component/auth/Register'
import Profile from './component/pages/Profile';
import jwt_decode from 'jwt-decode';
import setAuthToken from './utils/setAuthToken';
import { Provider } from 'react-redux';
import PrivateRoute from './component/common/PrivateRoute';
import store from './store';
function App() {
return (
<Provider store={store}>
<Router>
//this is the pages i want to hide the <Header/> and <Sidebar/> from
<Route exact path="/" component ={Login}/>
<Route exact path="/Signup" component ={Signup}/>
<Route exact path="/Reset" component ={Reset}/>
//this is where they ends
<Header/>
<Sidebar/>
<div id= "main-wrapper">
<Route path="/Shipped" component ={Shipped}/>
<Route path="/Warehouse" component ={Warehouse}/>
<Route path="/Assisted" component ={Assisted}/>
<Route path="/Profile" component ={Profile}/>
</div>
</Router>
</Provider>
);
}
export default App;
I think your making the code too overcomplicated, some steps I would introduce the following below.
Create a component called <Wrapper>, this should deal with the header responsibility. Just wrap this in every UI that you need it. You are building a variable which adds code duplication and could become a performance problem if you had 20 views which have no header..
<Wrapper />:
const Wrapper = ({ children }) => (
<>
<Head />
{children}
</>
);
On a side note, I think extracting data and jsx make for easier testing and if done correctly makes for easy code reviews!
This is what I would do with your routes:
routes.js:
// Import routes here...
const routes = [
{
path: "Login",
component: Login
},
{
path: "Reset",
component: Reset
},
{
path: "Confirm",
component: Confirm
},
{
path: "Signup",
component: Signup
},
{
path: "/Warehouse",
component: Warehouse
},
{
path: "/Assisted",
component: Assisted
},
{
path: "/Profile",
component: Profile
},
{
path: "/shipped",
component: Shipped,
exact: true
}
];
The benefit here is that you divide and separate out concerns in the app it makes debugging easier to deduce. This main component only cares about rendering routes, it also means your <App /> has only app required import not a block of route component imports.
Now your <App /> can be nice and small for example:
const App = () => (
<Provider {...{ store }}>
<Router>
<div id="main-wrapper">
{routes.map(route => (
<Route key={route.path} {...route} />
))}
</div>
</Router>
</Provider>
);
I hope this helps, let me know how you get on!
All i did was use a let statement to condition the header in the pages
import React, {Component} from 'react';
import {BrowserRouter as Router, Route, Switch} from 'react-router-dom';
import Head from './component/layout/Head';
import Shipped from './component/pages/Shipped';
import Warehouse from './component/pages/Warehouse';
import Assisted from './component/pages/Assisted';
import Login from './component/auth/Login'
import Profile from './component/pages/Profile';
import jwt_decode from 'jwt-decode';
import setAuthToken from './utils/setAuthToken';
import { Provider } from 'react-redux';
import PrivateRoute from './component/common/PrivateRoute';
import store from './store';
class App extends Component {
render(){
let HideHeader = window.location.pathname === '/Login' && '/Reset' && '/Confirm' && '/Signup' ? null : <Head/>
return (
<Provider store={store}>
<Router>
<div id= "main-wrapper">
{HideHeader}
<Route path="/Login" component={Login} />
<Route path="/Warehouse" component ={Warehouse}/>
<Route path="/Assisted" component ={Assisted}/>
<Route path="/Profile" component ={Profile}/>
<Route exact path="/shipped" component={Shipped} />
</div>
</Router>
</Provider>
);
}
}
export default App;
Related
I have to combine use of Redux and React Router.
I tried react Router alone first and when I was clicking my images I was correctly redirected.
I followed redux tutorial and now when I click my images, I change the address (ex: http://localhost:3000/contact) but nothing displays as if the component was empty.
Root.js
import React from 'react';
import './index.css';
import PropTypes from 'prop-types'
import ReactDOM, { BrowserRouter as Router, Route, Link, Switch } from 'react-router-dom'
import App from './App'
import Users from './users'
import Book from './Book'
import Notfound from './notfound'
import { Provider } from 'react-redux';
import Store from './redux/Store/store'
import * as serviceWorker from './serviceWorker';
const Root = ({ store }) => (
<Provider store = { Store }>
<Router>
<div>
<Switch>
<Route exact path="/:filter?" component={App} />
<Route path="/users" component={Users} />
<Route path="/book" component={Book} />
<Route path='/manual' component={() => { window.location = 'https://------'; return null;} }/>
<Route path='/contact' component={() => { window.location = 'https://-------'; return null;} }/>
<Route component={Notfound} />
</Switch>
</div>
</Router>
</Provider>
)
Root.propTypes = {
store: PropTypes.object.isRequired
}
serviceWorker.unregister();
export default Root
index.js:
import React from 'react'
import { render } from 'react-dom'
import { createStore } from 'redux'
import myReducer from './redux/Reducers/myReducer'
import Root from './Root'
const store = createStore(myReducer)
render(<Root store={store} />, document.getElementById('root'))
App.js:
import React from 'react'
import { Route, Link, Redirect, withRouter, BrowserRouter as Router } from 'react-router-dom'
import logo from './images/logo.png';
import book from './images/book.png';
class App extends React.Component {
constructor() {
super();
this.state = {
date: new Date()
};
}
render() {
const { date } = this.state;
return (
<div>
<img src={logo} />
<img src={book} onClick={() => this.props.history.push('/book')}/>
<img src={call} onClick={() => this.props.history.push('/contact')}/>
</div>
)
}
}
export default App
Do you know what is wrong ?
A few things I noticed:
When using react router you shouldn't use window.location to redirect since this reloads the whole page. The <Redirect> component from react-router is a better choice here.
Also you shouldn't use the component prop on the <Route>-component for things that aren't actually components, as there's the render prop for that (more on that here).
Furthermore: <Route exact path="/:filter?" component={App} /> is not going to work since :filter? is looking for a variable and exact is looking for an exact match. Moreover you probably shouldn't put the flexible one first since it's going to match every route that you throw at it. So all the following routes are practically unreachable.
I have a Router File, where my Routes are nested under Index Component.
However, I want some other component, login which I don't want to Nest under any component but I want to use it to redirect to '/' home route.
If I use Div tags, then it is messing with my Template.
I am adding the Login component - route inside the Switch Tag.
If I don't do that I get React can only have one child error.
Does anyone know how to do a Nested Route and a Non-Nested One? Please Help.
This is my Router File.
import React, { Component } from 'react';
import './App.css';
import { Provider } from 'react-redux';
import store from './store/store';
import { Router, Route , Switch } from 'react-router-dom';
import Index from './actions/indexToggle/indexActions';
import FirstDashboard from './_layouts/views/firstDashboard';
import SecondDashboard from './_layouts/views/secondDashboard';
import ThirdDashboard from './_layouts/views/thirdDashboard';
import FourthDashboard from './_layouts/views/fourthDashboard';
import history from './history';
import FifthDashboard from './_layouts/views/fifthDashboard';
import Login from './_layouts/views/Login/login';
const Main = () => (
<Provider store={store}>
<Router history={history}>
<Switch>
<Index>
<Route exact path='/overview1' component={FirstDashboard} />
<Route exact path='/overview2' render={(props) => <SecondDashboard {...props} show="show" /> } />
<Route exact path='/overview3' component={ThirdDashboard} />
<Route exact path='/overview4' component={FourthDashboard} />
<Route exact path='/overview5' component={FifthDashboard} />
</Index>
<Route path='/login' component={Login} />
</Switch>
</Router>
</Provider>
)
export default Main;
Here what I've done. See DEMO.
I don't wanna be too confused because of this, so I choose a simple way.
routes.js
import Home from "./pages/Home";
import ComplexPath from "./pages/ComplexPath";
import Login from "./pages/Login";
export default [
{
path: "/",
component: Home,
withHeaderSidenav: true
},
{
path: "/yet/another/complex/path",
component: ComplexPath,
withHeaderSidenav: true
},
{
path: "/login",
component: Login,
withHeaderSidenav: false
}
];
Then, simply map the routes.
App.js
import React from "react";
import { Switch, Route } from "react-router-dom";
import BaseLayout from "./BaseLayout";
import routes from "./routes";
export default class extends React.Component {
state = {
withHeaderSidenav: true
};
showHeaderSidenav = (withHeaderSidenav = true) => {
this.setState({ withHeaderSidenav });
};
render() {
return (
<BaseLayout withHeaderSidenav={this.state.withHeaderSidenav}>
<Switch>
{routes.map(route => (
<Route
exact
key={route.path}
path={route.path}
render={() => (
<route.component
showHeaderSidenav={() =>
this.showHeaderSidenav(route.withHeaderSidenav)
}
/>
)}
/>
))}
</Switch>
</BaseLayout>
);
}
}
There will be a HOC for each page to handle layout changing. See pages/withBase.js in demo project.
I am currently experimenting with the use of React Router on the website I am building. I came across the use of React Router in order to navigate through my website, and also do other things like read parameter values etc. However, I find it to be slightly confusing. You see, on my administrator login page, the router only works some times - but I haven't really figured out when and when not. I am using this.props.history.push('/admin/dashboard'), which I believe is the correct way of doing it. This is currently my setup in index.js where i have all my routes:
import React from 'react';
import ReactDOM from 'react-dom';
import registerServiceWorker from './registerServiceWorker';
import './css-styling/styling.css'
import Frontpage from './Frontpage';
import { BrowserRouter, Route, Router, Switch, Link, NavLink } from 'react-router-dom';
import AdminLogin from './Admin-Login';
import AdminWelcome from './Admin-Welcome';
import Authentication from './components/Authentication';
const websiteRoutes = (
<Router history={history}>
<div>
<Switch>
<Route path="/" component={Frontpage} exact={true}/>
<Route path="/admin" component={AdminLogin} exact={true}/>
<Authentication props={this.props}>
<Route path="/admin/welcome" component={AdminWelcome} exact={true}/>
</Authentication>
</Switch>
</div>
</Router>
);
var appRoot = document.getElementById('root');
registerServiceWorker();
ReactDOM.render(websiteRoutes, appRoot);
And each 'component' has its structure like this:
import React from 'react';
import ReactDOM from 'react-dom';
import AdminHeader from './components/Admin-Header';
import AdminPanelLogin from './components/Admin-Panel-Add-News';
import history from './components/History';
class AdminLogin extends React.Component{
render() {
return(
<div>
<AdminHeader />
<AdminPanelLogin />
</div>
);
}
}
export default AdminLogin;
What seem to be the problem here? I have tried a lot of different solutions, without having any luck. One of them was creating this 'global history', which you can see that I have imported in my AdminAddNews class.
What is the correct way of using React Router in my case?
By the way; The history.push happens inside my AdminPanelLogin component, where the code looks like this:
import React from 'react';
import ReactDOM from 'react-dom';
import { Icon, Input, Button, Message } from 'semantic-ui-react';
import {auth} from './Firebase';
import {NotificationContainer, NotificationManager} from 'react-notifications';
import { withRouter, Redirect } from 'react-router-dom';
import history from './components/History';
class AdminLogin extends React.Component{
constructor(props){
super(props);
this.handleLogin = this.handleLogin.bind(this);
this.clickLogin = this.clickLogin.bind(this);
this.performLogin = this.performLogin.bind(this);
}
handleLogin(e){
this.setState({
[e.target.name]: e.target.value
});
}
clickLogin(e){
e.preventDefault();
auth.signInWithEmailAndPassword(this.state.email, this.state.password).then(() => {
this.props.history.push('/admin/dashboard');
}).catch((error)=> {
})
}
render() {
return (
<HTMLGOESHERE>
);
}
}
export default AdminLogin;
Few things, that you need to correct,
First: In your Routes you have passed history but you have not created a custom history anywhere. You can simply use BrowserRouter for now.
Second: Write your authentication component as Wrapper to your Routes instead of using your Routes as children to it
Authentication:
const PrivateRoute = (props) => {
const userKey = Object.keys(window.localStorage)
.filter(it => it.startsWith('firebase:authUser'))[0];
const user = userKey ? JSON.parse(localStorage.getItem(userKey)) : undefined;
if (user) {
return <Route {...props} />
} else {
return <Redirect to='/admin'/>
}
}
export default PrivateRoute;
Now you Routes can be
import { BrowserRouter as Router, Route, Router, Switch } from 'react-router-dom';
import Authentication from './Authentication';
const websiteRoutes = (
<Router>
<div>
<Switch>
<Route path="/" component={Frontpage} exact={true}/>
<Route path="/admin" component={AdminLogin} exact={true}/>
<Authentication path="/admin/welcome" component={AdminWelcome} exact={true}/>
</Switch>
</div>
</Router>
);
Apart from this check how to Programmatically Navigate with react-router
Actually, you have to use browserHistory, which is a function of react-router.I hope following snippet will help you,
Import react-router in your index.js
import {Router, Route, browserHistory} from 'react-router';
ReactDOM.render(
<Router history={browserHistory} >
<Route path="/admin/somethingZero" component={somethingZero} />
<Route path="/admin/somethingOne" component={somethingOne}/>
</Router> , document.getElementById("root")
)
you can navigate between the components, by using browserHistory.push function
clickLogin(){
browserHistory.push('/admin/dashboard')
}
Also, go on with this tutorial, it will give better understanding of routers.
I am learning redux with react and hit a mental roadblock, I have the following entry index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter, Redirect, Route} from 'react-router-dom';
import {Provider} from 'react-redux';
import store from './store';
import Bootstrap from 'bootstrap/dist/css/bootstrap.css';
import Main from './components/front/Main';
import Login from './components/front/Login';
import Home from './components/front/Home';
import Register from './components/front/Register';
import Forgot from './components/front/Forgot';
import Verify from './components/front/Verify';
import Dashboard from './components/back/Dashboard';
import './css/app.css';
import Auth from './components/Auth';
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={props => (
Auth.isLogged ? ( //<-need to get props here
<Component {...props}/>
) : (
<Redirect to={{
pathname: '/',
state: { from: props.location }
}}/>
)
)}/>
)
const App = () => (<BrowserRouter>
<div>
{/* PUBLIC */}
<Route path={'/'} exact component={Home}/>
<Route path={'/login'} component={Login}/>
<Route path={'/register'} component={Register}/>
<Route path={'/forgot'} component={Forgot}/>
<Route path={'/verify'} component={Verify}/>
{/* PRIVATE */}
<PrivateRoute path="/dashboard" component={Dashboard}/>
</div>
</BrowserRouter>);
ReactDOM.render(<Provider store={store}><App/></Provider>, document.getElementById('root'));
Overall redux works, the only problem is in this file, as I am not exporting anything, I can't get connect to work.
Ideally Auth.isLogged should be either true or false based on isAuthenticated prop, but I can't get the value passed in any way to the entry index.js
import React from 'react';
import { connect } from 'react-redux';
#connect((store) => {
return {isAuthenticated: store.auth.isAuthenticated, authenticating: store.auth.authenticating};
})
export default class Auth extends React.Component {
//Can't get anything from here to index.js
}
Please any help would be greatly appreciated!
If I understand correctly, you’re trying to provide context of store.auth.isAuthenticated to PrivateRoute.
If you declare App in its' own file you can connect it to the store and then pass the value of isAutenticated to your PrivateRoute component
//App.js
import React, { Component } from 'react'
import { withRouter, Switch, Route } from 'react-router-dom'
import { connect } from 'react-redux'
import PrivateRoute from 'components/PrivateRoute'
#withRouter
#connect(store => ({
isAuthenticated: store.auth.isAuthenticated,
authenticating: store.auth.authenticating
}))
class App extends Component {
render() {
const { isAuthenticated } = this.props
return (
<span>
{/* PUBLIC */}
{ !isAuthenticated &&
<Switch>
<Route path={'/'} exact component={Home}/>
<Route path={'/login'} component={Login}/>
<Route path={'/register'} component={Register}/>
<Route path={'/forgot'} component={Forgot}/>
<Route path={'/verify'} component={Verify}/>
</Switch>
}
{/* PRIVATE */}
{ isAuthenticated &&
<PrivateRoute
isAuthenticated={isAuthenticated}
path="/dashboard"
component={Dashboard}
/>
}
</span>
)
}
}
export default App
For readability sake you could make this change in index.js
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>,
document.getElementById('root')
)
You may or may not need to wrap connect(App) inside of withRouter, but the way I was handling my routing made this part necessary.
I know this has been asked before but none of the answers applied to me so here goes. I have this basic route setup:
import React from 'react'
import { Router, Route, IndexRoute, browserHistory } from 'react-router'
import CoreLayout from 'layouts/CoreLayout/CoreLayout'
import AuthLayout from 'layouts/AuthLayout/AuthLayout'
import HomeView from 'views/Home/HomeView'
import AuthView from 'views/Auth/AuthView'
import SignupView from 'views/Signup/SignupView'
export default ( store ) => (
<Router history={browserHistory}>
<Route path='/' component={CoreLayout}>
<IndexRoute component={HomeView}/>
</Route>
<Route component={AuthLayout}>
<Route path="/signup" component={SignupView} />
<Route path="/auth" component={AuthView} />
</Route>
</Router>
)
I also have a button that, when pushed, should redirect to another page browserHistory.push( '/signup' ). When clicked, I can see the url updating in the browser but the component is not mounting. Any idea what am I doing wrong here?
As requested, here's my AuthLayout:
import React, { PropTypes } from 'react'
import 'styles/core.scss'
function AuthLayout( { children } ) {
return (
<div className='page-container'>
{children}
</div>
)
}
AuthLayout.propTypes = {
children: PropTypes.element
};
export default AuthLayout