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
Related
I'm trying to wrap Routes using Layout component so it puts all content into a bootstrap 12 column grid.But it doesnt wrap my text inside Route components and I get a warning that functions are not valid as a React child. Here is the App.js code:
import './App.css';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import Home from './Home';
import Offers from './Offers';
import Financing from './Financing';
import Buying from './Buying';
import Contact from './Contact';
import Gallery from './Gallery';
import Search from './Search';
import Layout from './components/Layout';
function App() {
return (
<Fragment>
<Layout>
<Router>
<Routes>
<Route path='/' element={Home} />
<Route path='/fahrzeugangebote/' element={Offers} />
<Route path='/finanzierung/' element={Financing} />
<Route path='/fahrzeugankauf/' element={Buying} />
<Route path='/galerie/' element={Gallery} />
<Route path='/kontakt/' element={Contact} />
<Route element={Search} />
</Routes>
</Router>
</Layout>
</Fragment>
);
}
export default App;
And here is the code for Layout.js:
import Container from 'react-bootstrap/Container';
export const Layout = (props) => {
return(
<Container>
{props.children}
</Container>
)
};
export default Layout ```
As you can see in the docs, you have to provide the elements like this (ReactElement):
<Route path='/' element={<Home />} />
<Route path='/fahrzeugangebote/' element={<Offers />} />
// etc
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>
There is a #/ (hashbang) in my react route...
searching online yeilds covering <Route> with the new <BrowserRouter> will fix the problem
import React, { Component } from 'react';
import './App.scss';
import { observer } from 'mobx-react';
import { Header } from './components/Header'
import { Footer } from './components/Footer';
import { Route , BrowserRouter , Switch } from 'react-router-dom';
import MainState from './components/appset/MainState';
import HomePage from './components/HomePage';
import { TestContent } from './components/TestContent';
import { Account } from './components/Account';
import { TokenList } from './components/TokenList';
import { TokenPage } from './components/TokenPage';
import ErrorPage from './components/ErrorPage';
class Layout extends Component {
render() {
return (
<div id="bodyWheel" className={`App ${MainState.currentTheme} ${MainState.currentLang}`}>
<Header />
<div id="App-intro" className={this.state.resolutionHeight}>
<div className="container">
<div className="layout-main">
<BrowserRouter>
<Route path="/" exact component={HomePage} />
<Route path="/test" component={TestContent} />
<Route path="/account/:id" exact component={Account} />
<Route path="/token" exact component={TokenPage} />
<Route path="/token/:id" exact component={TokenList} />
<Route path="/operation/:id" exact component={HomePage}/>
<Route path="/error/:id" exact component={ErrorPage} />
</BrowserRouter>
</div>
</div>
</div>
<Footer />
</div>
);
}
}
export default Layout;
It adds #/ by itself at the end of every route for example:
www.foo.com/account/tera
becomes
www.foo.come/account/tera#/
<BrowserRouter> did nothing at all.
Will building and uploading to a webserver instead of running on 'npm start' fix the problem?
(edit:) turns out <BrowserRouter> works but something just keeps adding#/to the end of my routes the routs without#/` works just fine
fix is in the <BrowserRouter> edit to <BrowserRouter basename="">
and cover the main div
<BrowserRouter basename="">
<div id="bodyWheel" className={`App ${MainState.currentTheme} ${MainState.currentLang}`}>
....
</div>
</BrowserRouter>
fixed all the routing problems!
The problem is that when I try to copy a route directly I get this error:
Cannot Get / home
But when I navigate with the menu items I usually render the views, I have tried several ways as browserHistory to achieve that effect but I do not succeed, I wonder, if react-router-dom does not allow navigation directly in the URL or is it an error in my code:
// Dependencies
import React, { Component} from 'react'
import { render } from 'react-dom'
import { BrowserRouter as Router, Route, browserHistory, Link} from 'react-router-dom'
//components
class App extends Component{
render(){
return(
<div>
<h1>App!</h1>
<ul>
<li><Link to="/home"> Home</Link></li>
<li><Link to="/about"> About </Link></li>
<li><Link to="/contact"> Contact </Link></li>
</ul>
</div>
)
}
}
class Home extends Component {
render() {
return(
<h2>Home Page!</h2>
)
}
}
class About extends Component{
render() {
return(
<h2>About Page!</h2>
)
}
}
class Contact extends Component {
render() {
return(
<h2>Contact Page!</h2>
)
}
}
// routes
render(
<Router history={browserHistory}>
<div>
<Route component={App} path="/" />
<Route component={Home} path="/home" />
<Route component={About} path="/about" />
<Route component={Contact} path="/contact" />
</div>
</Router>,
document.getElementById('app')
);
I have solved it! for those who have the same error, I share what I did; to see the problem if it was from the server so I had to configure webpack with "historyApiFallback: true" or put "--historyApiCallback" in the script of webpack dev server in the package.json luck :)