Skip to content

Commit

Permalink
Merge pull request #11 from PAkerstrand/fix/support-named-components
Browse files Browse the repository at this point in the history
Add support for named components
  • Loading branch information
dlmr authored Oct 27, 2016
2 parents e78e0bd + 894fe8e commit 268c074
Show file tree
Hide file tree
Showing 28 changed files with 578 additions and 64 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ lib
.DS_Store
.nyc_output
coverage
yarn.lock
10 changes: 10 additions & 0 deletions examples/named-components/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"presets": [
"es2015",
"stage-1",
"react"
],
"plugins": [
"transform-decorators-legacy"
]
}
4 changes: 4 additions & 0 deletions examples/named-components/client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import render from './render/client';
import routes from './routes';

render(document.getElementById('application'), routes);
27 changes: 27 additions & 0 deletions examples/named-components/components/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React, { Component } from 'react';
import { Link, IndexLink } from 'react-router';

export default class App extends Component {
render() {
const { loading } = this.props;
const style = {
opacity: loading ? 0.5 : 1,
transition: loading ? 'opacity 250ms ease 300ms' : 'false',
};

return (
<div style={style}>
<h1>React Router Redial Example</h1>
<ul>
<li>
<IndexLink to="/">Start</IndexLink>
</li>
<li>
<Link to="/named">Named components</Link>
</li>
</ul>
{this.props.children}
</div>
);
}
}
32 changes: 32 additions & 0 deletions examples/named-components/components/Footer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React, { Component } from 'react';
import { provideHooks } from 'redial';

class Footer extends Component {
render() {
return (
<div>
<span>Copyright © {this.props.year}</span>
<span>Made with ❤ by people</span>
<span>Additional stuff. You know. Because we can.</span>
</div>
);
}
}

const enhance = provideHooks({
fetch: ({ setProps, getProps, force }) => new Promise((resolve) => {
const { year } = getProps();
if (!year || force) {
setTimeout(() => {
setProps({
year: new Date().getFullYear(),
});
resolve();
}, 250);
} else {
resolve();
}
}),
});

export default enhance(Footer);
28 changes: 28 additions & 0 deletions examples/named-components/components/Header.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React, { Component } from 'react';
import { Link } from 'react-router';
import { provideHooks } from 'redial';

@provideHooks({
fetch: ({ setProps, getProps, force }) => new Promise((resolve) => {
const { color } = getProps();
if (!color || force) {
setTimeout(() => {
const getValue = () => Math.round(Math.random() * 255);
setProps({ color: `rgb(${getValue()}, ${getValue()}, ${getValue()})` });
resolve();
}, 1000);
} else {
resolve();
}
}),
})
export default class Header extends Component {
render() {
return (
<div>
<h2 style={{ color: this.props.color }}>I am but a simple header, doing my thing.</h2>
<Link to="/named/with-children">Checkout more stuff!</Link>
</div>
);
}
}
36 changes: 36 additions & 0 deletions examples/named-components/components/Index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, { Component } from 'react';
import { provideHooks } from 'redial';

@provideHooks({
fetch: ({ setProps, getProps, force }) => new Promise((resolve) => {
const { color } = getProps();
if(!color || force) {
setTimeout(() => {
const getValue = () => Math.round(Math.random() * 255);
setProps({color: `rgb(${getValue()}, ${getValue()}, ${getValue()})`});
resolve();
}, 1000);
} else {
resolve();
}
}),
defer: ({ setProps, getProps, force }) => {
const { data } = getProps();
if (!data || force) {
// Will be available as this.props.data on the component
setProps({ data: 'Client data' });
}
},
})
export default class Index extends Component {
render() {
return (
<div>
<h1 style={{ color: this.props.color }}>React Router Redial</h1>
<p>{ this.props.data }</p>
<button onClick={ () => this.props.reload() }>Reload color</button>
<pre>{ JSON.stringify(this.props, null, 2) }</pre>
</div>
);
}
}
40 changes: 40 additions & 0 deletions examples/named-components/components/LoremIpsum.js

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions examples/named-components/components/Main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React, { Component } from 'react';

class Main extends Component {
render() {
return (
<div>
It's so much fun to be Malcolm in the Middle!
{this.props.children}
</div>
);
}
}

export default Main;
23 changes: 23 additions & 0 deletions examples/named-components/components/NamedContainer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React, { Component } from 'react';

export default class NamedContainer extends Component {
render() {
const { header, footer, main } = this.props;
return (
<div>
<div>
<h1>Header fragment</h1>
{header}
</div>
<div>
<h1>Main fragment</h1>
{main}
</div>
<div>
<h1>Footer fragment</h1>
{footer}
</div>
</div>
)
}
}
26 changes: 26 additions & 0 deletions examples/named-components/devServer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import koa from 'koa';
import webpack from 'webpack';
import koaWebpackDevMiddleware from 'koa-webpack-dev-middleware';

import webpackConfig from './webpack.config.js';

const devServer = koa();
const compiler = webpack(webpackConfig);

devServer.use(
koaWebpackDevMiddleware(compiler, {
publicPath: '/',
noInfo: false,
quiet: false
})
);

const hotMiddleware = require('webpack-hot-middleware')(compiler);
devServer.use(function* (next) {
yield hotMiddleware.bind(null, this.req, this.res);
yield next;
});

devServer.listen(3001);

console.log('Dev server started on http://localhost:3001');
32 changes: 32 additions & 0 deletions examples/named-components/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "react-router-redial-simple-example",
"version": "0.0.0",
"description": "React Router Redial simple example",
"scripts": {
"start": "babel-node server.js"
},
"license": "MIT",
"dependencies": {
"isomorphic-fetch": "2.2.1",
"koa": "1.2.0",
"nunjucks": "2.4.2",
"react": "^15.0.2",
"react-dom": "^15.0.2",
"react-router": "^2.5.2",
"react-router-redial": "^0.1.3",
"redial": "^0.5.0"
},
"devDependencies": {
"babel-cli": "6.8.0",
"babel-core": "6.8.0",
"babel-loader": "6.2.4",
"babel-plugin-transform-decorators-legacy": "1.3.4",
"babel-polyfill": "6.9.0",
"babel-preset-es2015": "6.6.0",
"babel-preset-react": "6.5.0",
"babel-preset-stage-1": "6.5.0",
"koa-webpack-dev-middleware": "1.2.0",
"webpack": "1.13.0",
"webpack-hot-middleware": "2.10.0"
}
}
46 changes: 46 additions & 0 deletions examples/named-components/render/client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { useRedial } from 'react-router-redial';

import React from 'react';
import { render } from 'react-dom';
import { Router, browserHistory, applyRouterMiddleware } from 'react-router';

// Render the app client-side to a given container element:
export default (container, routes) => {
const forcePageReloadOnError = true;
const goBackOnError = false;

// Function that can be used as a setting for useRedial
function onError(err, { abort, beforeTransition, reason, router }) {
if (process.env.NODE_ENV !== 'production') {
console.error(reason, err);
}

// We only what to do this if it was a blocking hook that failed
if (beforeTransition) {
if (forcePageReloadOnError && reason === 'other') {
window.location.reload();
} else if (goBackOnError && reason !== 'location-changed') {
router.goBack();
}
// Abort current loading automatically
abort();
}
}

const component = (
<Router
history={browserHistory}
routes={routes}
render={applyRouterMiddleware(useRedial({
beforeTransition: ['fetch'],
afterTransition: ['defer', 'done'],
parallel: true,
initialLoading: () => <div>Loading…</div>,
onError,
}))}
/>
);

// Render app to container element:
render(component, container);
};
27 changes: 27 additions & 0 deletions examples/named-components/render/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { triggerHooks, useRedial } from '../../../lib/index';

import { renderToString } from 'react-dom/server';
import { createMemoryHistory, match, applyRouterMiddleware } from 'react-router';

// Render the app server-side for a given path:
export default (path, routes) => new Promise((resolve, reject) => {
// Set up history for router:
const history = createMemoryHistory(path);

// Match routes based on history object:
match({ routes, history }, (error, redirectLocation, renderProps) => {
if (error || !renderProps) {
return reject(error);
}

// Wait for async data fetching to complete, then render:
return triggerHooks({
renderProps,
hooks: ['fetch', 'done'],
}).then(({ redialMap, redialProps }) => {
const html = renderToString(applyRouterMiddleware(useRedial({ redialMap }))(renderProps));
resolve({ html, redialProps });
})
.catch(reject);
});
});
21 changes: 21 additions & 0 deletions examples/named-components/routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import { Route, IndexRoute } from 'react-router';

import App from './components/App';
import Footer from './components/Footer';
import Head from './components/Header';
import Index from './components/Index';
import LoremIpsum from './components/LoremIpsum';
import Main from './components/Main';
import NamedContainer from './components/NamedContainer';

export default (
<Route path="/" component={App}>
<IndexRoute component={Index} />
<Route component={NamedContainer}>
<Route path="named" components={{ header: Head, footer: Footer, main: Main }}>
<Route path="with-children" component={LoremIpsum} />
</Route>
</Route>
</Route>
);
20 changes: 20 additions & 0 deletions examples/named-components/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import koa from 'koa';
import nunjucks from 'nunjucks';

import render from './render/server';
import routes from './routes';

require('./devServer');

nunjucks.configure(__dirname);

const server = koa();
server.use(function *() {
const result = yield render(this.url, routes);
this.body = nunjucks.render('template.html', {
...result,
redialProps: JSON.stringify(result.redialProps)
});
});
server.listen(3000);
console.log('Server started on http://localhost:3000');
11 changes: 11 additions & 0 deletions examples/named-components/template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div id="application">{{ html | safe }}</div>
<script>window.__REDIAL_PROPS__ = {{ redialProps | safe }}</script>
<script src="http://localhost:3001/bundle.js"></script>
</body>
</html>
Loading

0 comments on commit 268c074

Please sign in to comment.