I have a React JS component am attempting to load into a page after a user has logged in. This secure page consist of tabs and upon clicking the tabs, content is loaded from the tabs respective component.
Currently, the main component loads when it's tab is clicked, however I'm attempting to also have that main page load automatically following user login.
This is the Code behind the master page:
import React, { Component } from 'react';
import './App.css';
import AuthService from './components/AuthService';
import withAuth from './components/withAuth';
import Footer from './components/Footer';
import Navigation from './components/Navigation';
import {
Route,
NavLink,
HashRouter
} from "react-router-dom";
import Main from './components/Main';
import Catalog from './components/Catalog ';
import Calendar from './components/Calendar';
const Auth = new AuthService();
class App extends Component {
render() {
return (
<div className="App">
<div className="App-header">
<div className="App-title"><h2>Catalog</h2></div>
<div>
<p className="App-logout">
<button type="button" className="form-submit" onClick={this.handleLogout.bind(this)}>Logout</button>
</p>
</div>
</div>
<div className="App-divider"></div>
<div>
<Navigation />
</div>
<div className="App-content">
<HashRouter>
<Route exact path="/main" component={Main} />
</HashRouter>
<HashRouter>
<Route path="/catalog" component={Catalog} />
</HashRouter>
<HashRouter>
<Route path="/calendar" component={Calendar} />
</HashRouter>
</div>
<div>
<Footer />
</div>
</div>
);
}
handleLogout() {
Auth.logout()
this.props.history.replace('/login');
}
}
export default withAuth(App);
Am still new to React JS, could I get some help with this? ...Thanks
You probably should separate your unauthenticated views and authenticated views.
Have a login page that stores auth credentials however you'd like, (redux, locally, cookies, etc) then create a route that only shows once the user has auth...
<Route exact path="/login" component={() => !this.props.auth ? <LoginPage /> : <Redirect to="/HomePage" />}
/>
// You could also use !this.state.auth, or any other variable you are using to handle auth.
Related
I have two components,
App and Dashboard
App Component is the main component, inside App, there is a switch to the Dashboard component
I need nested route, Inside Dashboard Component, I need to have "/dashboard/blogs" which switch the Blogs Component inside it.
Here I share the two components,
import React, { Component } from "react";
import {BrowserRouter as Router, Route, Switch} from "react-router-dom";
import Signup from "./pages/Signup";
import Login from "./pages/Login";
import Home from "./pages/Home";
import Dashboard from "./dashboard/Dashboard";
class App extends Component {
render() {
return (
<div id="content-wrapper">
<Router>
<Switch>
<Route exact path="/signup" component={Signup}/>
<Route exact path="/login" component={Login}/>
<Route exact path="/" component={Home}/>
<Route exact path="/dashboard" component={Dashboard}/>
</Switch>
</Router>
</div>
);
}
}
export default App;
import React, {Component} from 'react';
import Navbar from "./Navbar";
import SideBar from "./SideBar";
import "../scripts/dashboard";
import {BlogList} from "./components/BlogList";
import {BrowserRouter as Router, Route, Switch} from "react-router-dom";
import {DashBoardHome} from "./components/DashBoardHome";
class Dashboard extends Component {
render()
{
return (
<div id="wrapper">
<SideBar/>
<div id="content-wrapper" className="d-flex flex-column">
<div id="content">
<Navbar/>
<div className="container-fluid">
<Router>
<Switch>
<Route path={`${this.props.match.url}/blogs`} exact={true} component={BlogList} /> //This is not working?
</Switch>
</Router>
</div>
</div>
</div>
</div>
)
}
}
export default Dashboard;
Thanks In Advance!
The problem is the exact keyword.
<Route exact path="/dashboard" component={Dashboard}/>
With this code snippet you basically say, that the Dashboard component should only be rendered when the URL address is exactly ".../dashboard".
<Route path={`${this.props.match.url}/blogs`} exact={true} component={BlogList} />
With this code snippet you say, that BlogList component should be rendered only when the URL is exactly ".../dashboard/blogs/", but it is rendered inside Dashboard component witch is not rendered, because the URL is not ".../dashboard".
Removing exact keyword from <Route path="/dashboard" component={Dashboard} /> should fix your code.
I am fairly new to react but I have been told when making a website its good practice to have a layout component which holds the header, page content and footer however when using react router I want the header and footer to not update just the page content but if I add the links in the header outside the browserrouter tag I get a error saying they need to be inside but if i then include them inside the header updates along with the content..
In the header I have a navbar with links like this:
import React from 'react';
import { Link } from 'react-router-dom';
const Header = () => {
return(
<nav className="header-links">
<Link to="/" className="link">Home</Link>
<Link to="/about" className="link">About</Link>
<Link to="/contact" className="link">Contact Us</Link>
</nav>
);
}
export default HeaderNav;
Then in the layout file I include the header which has the links
import React from 'react'
import Header from './header/header'
import Footer from './footer/footer'
const PageLayout = ({children}) => {
return (
<div className="layout-wrapper">
<Header />
<main className="site-content">{children}</main>
<Footer />
</div>
);
}
export default PageLayout;
Then I also have a router file with my routes:
import React from 'react'
import HomePage from './pages/home'
import AboutPage from './pages/about'
import ContactPage from './pages/contact'
import {
Switch,
Route,
BrowserRouter
} from 'react-router-dom';
const Routes = () => (
<BrowserRouter>
<Switch>
<Route exact path="/" component={HomePage} />
<Route exact path="/about" component={AboutPage} />
<Route exact path="/contact" component={ContactPage} />
</Switch>
</BrowserRouter>
);
export default Routes;
The problem that I am having is if in the layout.js I only wrap the page content in the browserrouter tag then I get a error saying my links need to be inside this BUT if I then wrap the header, page content and footer in the browserrouter then they all update when a link is clicked so I am struggling with how do I include the links in the browserrouter without the header updating?
For instance:
import React from 'react'
import Header from './header/header'
import Footer from './footer/footer'
const PageLayout = ({children}) => {
return (
<div className="layout-wrapper">
<Routes>
<Header />
<main className="site-content">{children}</main>
<Footer />
<Routes />
</div>
);
}
export default PageLayout;
I might be totally off base here, but I'm pretty sure you want something like this:
<BrowserRouter>
<Header/>
<Switch>
<Route exact path="/" component={HomePage} />
<Route exact path="/about" component={AboutPage} />
<Route exact path="/contact" component={ContactPage} />
</Switch>
<Footer />
</BrowserRouter>
I'm using HashRouter in my application to prevent it from breaking when a page gets refreshed, or when a user tries to navigate to a specific route (ex: mysite.com/about)
How would I go about using page jumps in a tags? Something like this:
Contact Me
just navigates back to the start page with HashRouter. Is there any way to rewrite the link to have it jump down to the specific id?
index.js
...
import { HashRouter } from 'react-router-dom';
ReactDOM.render(
<HashRouter>
<App />
</HashRouter>, document.getElementById('root'));
registerServiceWorker();
App.js
import React, { Component } from 'react';
import { Switch, Route } from 'react-router-dom';
... //import for the components
class App extends Component {
render() {
return (
<div className="App">
<TopNav />
<div className="app-container">
<SideNav />
<div className="app-content">
<Switch>
<Route exact path='/' component={Home} />
<Route path='/about' component={About} />
<Route path='/projects' component={Projects} />
...
</Switch>
</div>
</div>
<BottomNav />
</div>
);
}
}
export default App;
Before I begin I have been on the https://reacttraining.com/react-router/web/guides/quick-start to grasp the idea of how the react router works. I have created a simple 3 page site in react and I want to create a list which will allow me to show some nested components. Whilst the examples on reacttraining.com nicely work on in a singles js file. I have my site split over 3 js files:
APP.JS
import React, {Component} from 'react';
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom';
import {Home} from './Home';
import {User} from './User';
import {Artwork} from './artwork'
import {Header} from './header';
class App extends Component {
render(){
return (
<Router>
<div className="container">
<div className="row">
<div className="col-xs-10 col-xs-offset-1">
<Header />
</div>
</div>
<hr/>
<div className="row">
<div className="col-xs-10 col-xs-offset-1">
<Route path="/" exact component={Home}/>
<Route path="/home" exact component={Home}/>
<Route path="/user" component={User}/>
</div>
</div>
</div>
</Router>
);
}
}
export default App;
USER.JS Edited on 28/03/2017
import React, {Component} from 'react';
import {Artwork} from './artwork';
import {Route, Link} from 'react-router-dom';
export class User extends Component {
render() {
return (
<div className="row">
<div className="col-md-4">
<h3>The User Page</h3>
<p>User ID:</p>
<li><Link to="/user/artwork">Artwork</Link></li>
</div>
<div className="col-md-8">
<Route path="/user/artwork" component={Artwork}/>
</div>
</div>
);
}
}
export default User;
ARTWORK.JS
import React, {Component} from 'react';
export class Art extends Component {
render(){
return (
<div>
<h3>Art</h3>
</div>
);
}
}
export default Art;
The issue that I am having is that whilst i can navigate through to my top level menu items (Home and User) I can not access the artwork component on the the user page. when the artwork button is pressed my user component is removed.
If you're looking at the basic example on react-training, you'll notice that the "child" Route in the Topics component has ${match.url}/:topicId as the path:
<Route path={`${match.url}/:topicId`} component={Topic}/>
This is basically turning it into topics/:topicId which is needed because the top most component wouldn't know what to do with just :topicId.
Likewise, in your situation, your App.js doesn't know what to do with /artwork so it doesn't render anything. If you change your Route path and Link to in User.js to /user/artwork it should start working as desired.
To make your User component more composable/reusable, you'd want to do the same thing as react training and use the passed in match.url on the props.
I am trying to create a Layout component which would render the Header and Footer. So that I can later on use the Layout like
<Layout> ... </Layout>
I have used Routing in the Header and Footer, obviously. To do this, I need to use
<Router history...
<Route path...
When I do this one after the other(for header and footer: though I feel that this is wrong) in my layout.js. It works. The header and footer are shown in the browser. However, they don't work properly. On refresh the footer vanishes and sometimes both, the header and the footer. I strongly believe that rendering Router one after the other is the reason for this malfunctioning, but I can't figure out the correct approach. Moreover, I don't want to use the following snippets
header.js
import React from 'react';
import {Link} from 'react-router'
import {Navbar, NavItem} from 'react-materialize';
export default React.createClass({
render(){
return (
<div>
<Navbar brand='logo' right>
<NavItem><Link to="/Home" activeClassName="active">Home</Link></NavItem>
<NavItem><Link to="/Sign-In" activeClassName="active">Sign In</Link></NavItem>
<NavItem><Link to="/Register" activeClassName="active">Register</Link></NavItem>
</Navbar>
{this.props.children}
</div>
)
}
})
footer.js
import React, {Component} from 'react';
import {Link} from 'react-router'
import {Footer} from 'react-materialize';
import '../../resource/template.css'
class RT_Footer extends Component{
render(){
return (
<div>
{this.props.children}
<Footer copyrights="© 2015 Copyright Text"
moreLinks={
<Link className="grey-text text-lighten-4 right" href="#!">More Links</Link>
}
links={
<ul>
<li><Link to="/About Us" className="grey-text text-lighten-3">About Us</Link></li>
<li><Link to="/Terms & Conditions" className="grey-text text-lighten-3">Terms & Conditions</Link></li>
<li><Link to="/Help" className="grey-text text-lighten-3">Help</Link></li>
<li><Link to="/Contact Us" className="grey-text text-lighten-3">Contact Us</Link></li>
</ul>
}
className='example'
>
<h5 className="white-text">Footer Content</h5>
<p className="grey-text text-lighten-4">You can use rows and columns here to organize your footer content.</p>
</Footer>
</div>
);
}
}
export default RT_Footer;
layout.js
import {Router, Route, browserHistory} from 'react-router'
class Layout extends Component {
render(){
return (
<div>
<span>
<Router history={browserHistory}>
<Route path="/" component={Header}>
<Route path="/Home" component={Home}/>
<Route path="/Sign-In" component={SignIn}/>
<Route path="/Register" component={Register}/>
</Route>
</Router>
</span>
<span>
<Router history={browserHistory}>
<Route path="/" component={RT_Footer}>
<Route path="/About Us" component={About}/>
<Route path="/Terms & Conditions" component={TC}/>
<Route path="/Register" component={Register}/>
</Route>
</Router>
</span>
</div>
);
}
}
export default Layout;
Then I simply rendered Layout in index.js
I suggest that you don't render the Router component twice (I haven't checked but you probably can't).
So, how the Router component works :
You give the router an history (via the history props), here you use the browserHistory from the same library wich is fine.
Then you define all the existing routes for your application using the Route component with a path, and the component to load if the browser url match this path property.
Now, in your case I suggest you to do something like that :
app.js
import {Router, Route, browserHistory} from 'react-router'
import Layout from './components/Layout'
// Import here all the required components used by the router such as SignIn, Register, ...
render(
<Layout>
<Router history={browserHistory}>
<Route path="/" component={RT_Footer}>
<Route path="/About Us" component={About}/>
<Route path="/Terms & Conditions" component={TC}/>
<Route path="/Register" component={Register}/>
// Add as many Route components as needed
</Router>
</Layout>,
document.getElementById('react-anchor')
Then your layout file should look like this :
layout.js
import Header from './Header'
import Footer from './Footer'
import React, {Component} from 'react'
class Layout extends Component {
render() {
return (
<div>
<Header />
{this.props.children}
<Footer />
</div>
)
}
}
And in your Header and Footer component, render whatever you want, to provide link to load the requested component you can use from react-router or some other way the library offer (see their documentation)
Edit :
Careful about route Path, like "Terms & Conditions" is probably not a valid path