Skip to content

Instantly share code, notes, and snippets.

@koistya
Last active July 1, 2021 16:05
Show Gist options
  • Star 31 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save koistya/ba7ad06d2624e10e07ee to your computer and use it in GitHub Desktop.
Save koistya/ba7ad06d2624e10e07ee to your computer and use it in GitHub Desktop.
React.js (ReactJS) Page and Layout components. For a complete sample visit https://github.com/kriasoft/react-starter-kit and http://reactjs.kriasoft.com (demo)

Page is URL-bound React component. For example, the /questions/votes URL on StackOverflow is bound to the <Questions sort="votes" /> component.

Layout is a wrapper for Page component, which itself can be wrapped in other layouts (for more complex pages). Layout usually contains header, footer, navigation, sidebar and other similar components as well as {this.props.children}.

It's is better to define the type of the layout to use on a Page lavel as opposed to somwhere else (e.g. in routing). Also at a page level you want to define page title either as a property or a state variable which is then passed to the layout component (or asynchronously via Flux's action creator).

With the layout approach # 1 (PageOne.jsx) the page can be rendered like this:

var React = require('react');
var copyProperties = require('react/lib/copyProperties');

/**
 * Check if Page component has a layout property; and if yes, wrap the page
 * into the specified layout, then mount to document.body.
 */
function render(page) {
  var child, props = {};
  while (page.defaultProps.layout) {
    child = page(props, child);
    copyProperties(props, page.defaultProps);
    page = page.defaultProps.layout;
  }
  React.renderComponent(page(props, child), document.body);
}

render(require('./pages/profile.jsx'));
/**
* Page layout, reused across multiple Page components
* @jsx React.DOM
*/
var React = require('react');
var ExecutionEnvironment = require('react/lib/ExecutionEnvironment');
var Navigation = require('../components/Navigation.jsx');
var DefaultLayout = React.createClass({
propTypes: {
title: React.PropTypes.string
},
render() {
return (
<div>
<div className="l-header">
<h1>Company Name</h1>
<Navigation />
</dv>
<div className="l-content">
<h1>{this.props.title}</h1>
{this.props.children}
</div>
<div className="l-footer">
<p>Copyright (c) 2014 Company Name</p>
</div>
</div>
);
},
componentDidMount() {
if (ExecutionEnvironment.canUseDOM) {
document.title = this.props.title;
}
}
});
module.exports = DefaultLayout;
/**
* Layout approach #1
* @jsx React.DOM
*/
var React = require('react');
var DefaultLayout = require('../layouts/DefaultLayout.jsx');
var PageOne = React.createClass({
getDefaultProps() {
return {
title: 'Page One',
layout: DefaultLayout
};
},
render() {
return (
<div>
<p>The page's content...</p>
<p>goes here.</p>
</div>
);
}
});
/**
* Layout approach #2
* @jsx React.DOM
*/
var React = require('react');
var DefaultLayout = require('../layouts/DefaultLayout.jsx');
var PageOne = React.createClass({
getDefaultProps() {
return {
title: 'Page Two'
};
},
render() {
return (
<DefaultLayout title={this.props.title}>
<p>The page's content...</p>
<p>goes here.</p>
</DefaultLayout>
);
}
});
@dschinkel
Copy link

dschinkel commented Aug 8, 2016

Where are you putting that function render(page) code. Do you have that in a .js file somewhere? And what is this child param for page()? where is that coming from and what are you doing with that when you pass it into the component as a param?

@Sheng-Long
Copy link

^ I had the same question, I just want a custom title for each page T.T

@sivasridhara
Copy link

Can you provide me the complete source code for this layout example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment