ReactJS Header and Footer

Roy picture Roy · Nov 7, 2016 · Viewed 51.5k times · Source

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="&copy; 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

Answer

Quentin picture Quentin · Nov 7, 2016

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