Skip to content
This repository has been archived by the owner on Jan 11, 2019. It is now read-only.

Commit

Permalink
Use React Transmit (Relay library) to replace react-async and remov…
Browse files Browse the repository at this point in the history
…e `fibers` dependency.
  • Loading branch information
RickWong committed Mar 27, 2015
1 parent 1bbc3f2 commit e513d33
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 70 deletions.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ Isomorphic starterkit with server-side React rendering using
[react.js](https://facebook.github.io/react),
[react-router](https://github.com/rackt/react-router),
[react-hot-loader](https://gaearon.github.io/react-hot-loader),
[react-async](https://github.com/andreypopp/react-async),
[react-a11y](https://github.com/rackt/react-a11y),
[react-inline-css](https://github.com/RickWong/react-inline-css)
[react-transmit](https://github.com/RickWong/react-transmit),
[react-inline-css](https://github.com/RickWong/react-inline-css),
[react-a11y](https://github.com/rackt/react-a11y)

## Features

Expand All @@ -24,7 +24,7 @@ Isomorphic starterkit with server-side React rendering using
- React.js + Router on the client and server
- React Hot Loader for instant client updates
- Babel.js automatically compiles ES6 + ES7
- React-async to preload on server to client
- React Transmit to preload on server to client
- InlineCss-component for styling components
- Accessibility hints from react-a11y

Expand All @@ -39,8 +39,9 @@ It just works out-of-the-box.
npm install
npm run watch # yes, one command for server and client development!

# production
NODE_ENV=production npm run build
# production build and run
NODE_ENV=production npm run build
NODE_ENV=production npm run browser

## Usage

Expand Down
9 changes: 4 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "react-isomorphic-starterkit",
"description": "Isomorphic starterkit with server-side React rendering.",
"version": "1.5.2",
"version": "2.0.0",
"license": "BSD-3",
"repository": {
"type": "git",
Expand All @@ -28,23 +28,22 @@
},
"dependencies": {
"babel": "4.7.16",
"fibers": "1.0.5",
"hapi": "8.4.0",
"piping": "0.1.7",
"react": "0.12.2",
"react-a11y": "0.0.6",
"react-async": "2.1.0",
"react-inline-css": "1.1.1",
"react-router": "0.12.4",
"superagent": "1.1.0"
"react-transmit": "2.0.0",
"isomorphic-fetch": "2.0.0"
},
"devDependencies": {
"babel-core": "4.7.16",
"babel-loader": "4.2.0",
"babel-runtime": "4.7.16",
"concurrently": "0.0.5",
"json-loader": "0.5.1",
"react-hot-loader": "1.2.3",
"react-hot-loader": "1.2.4",
"webpack": "1.7.3",
"webpack-dev-server": "1.7.0"
},
Expand Down
4 changes: 2 additions & 2 deletions src/client.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import ReactAsync from "react-async";
import Router from "react-router";
import Transmit from "react-transmit";
import routes from "views/Routes";

/**
Expand All @@ -14,7 +14,7 @@ if (process.env.NODE_ENV !== "production") {
* Fire-up React Router.
*/
Router.run(routes, Router.HistoryLocation, (Handler) => {
React.render(<Handler />, document.getElementById("react-root"));
Transmit.render(Handler, {}, document.getElementById("react-root"));
});

/**
Expand Down
21 changes: 9 additions & 12 deletions src/server.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {Server} from "hapi";
import React from "react";
import ReactAsync from "react-async";
import Router from "react-router";
import Transmit from "react-transmit";
import routes from "views/Routes";

/**
Expand Down Expand Up @@ -31,11 +31,9 @@ server.ext("onPreResponse", (request, reply) => {
}

Router.run(routes, request.path, (Handler, router) => {
ReactAsync.renderToStringAsync(
<Handler />,
(error, reactString, reactData) => {
let output = (
`<!doctype html>
Transmit.renderToString(Handler, {}, (reactString, reactData) => {
let output = (
`<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
Expand All @@ -46,13 +44,12 @@ server.ext("onPreResponse", (request, reply) => {
<div id="react-root">${reactString}</div>
</body>
</html>`
);
);

const webserver = process.env.NODE_ENV === "production" ? "" : "//localhost:8080";
output = ReactAsync.injectIntoMarkup(output, reactData, [`${webserver}/dist/client.js`]);
const webserver = process.env.NODE_ENV === "production" ? "" : "//localhost:8080";
output = Transmit.injectIntoMarkup(output, reactData, [`${webserver}/dist/client.js`]);

reply(output);
}
);
reply(output);
});
})
});
107 changes: 62 additions & 45 deletions src/views/Main.js
Original file line number Diff line number Diff line change
@@ -1,66 +1,45 @@
import React from "react";
import ReactAsync from "react-async";
import InlineCss from "react-inline-css";
import Superagent from "superagent";
import Transmit from "react-transmit";
import __fetch from "isomorphic-fetch";

/**
* Main React application entry-point for both the server and client.
*
* @class Main
*/
const Main = React.createClass({
mixins: [
ReactAsync.Mixin
],
/**
* Server and client.
*/
getInitialStateAsync (completedFn) {
componentWillMount () {
/**
* Load the first 100 stargazers on the server.
*/
if (__SERVER__) {
Main.loadStargazersFn([], false, 1, completedFn);
* Load the next 100 stargazers.
*/
if (__CLIENT__) {
this.props.setQueryParams({
prevStargazers: this.props.stargazers,
nextPage: this.props.queryParams.nextPage + 1,
pagesToFetch: this.props.queryParams.pagesToFetch - 1
});
}
},
/**
* Server and client.
* Client only.
*/
componentWillMount() {
if (__CLIENT__) {
/**
* Load the rest of the stargazers on the client.
*/
Main.loadStargazersFn(this.state.stargazers || [], true, 2, (error, state) => {
this.setState(state);
componentWillReceiveProps (nextProps) {
/**
* Load the rest of the stargazers repeatedly.
*/
if (nextProps.queryParams.pagesToFetch > 0) {
this.props.setQueryParams({
prevStargazers: nextProps.stargazers,
nextPage: nextProps.queryParams.nextPage + 1,
pagesToFetch: nextProps.queryParams.pagesToFetch - 1
});
}
},
statics: {
/**
* Use Superagent to retrieve the list of GitHub stargazers.
*/
loadStargazersFn (stargazers, untilAllLoaded, currentPage, completedFn) {
Superagent.get(
`https://api.github.com/repos/RickWong/react-isomorphic-starterkit/stargazers?per_page=100&page=${currentPage}`
).
end((error, response) => {
if (response && Array.isArray(response.body)) {
stargazers = stargazers.concat(response.body.map((user) => {
return {
id: user.id,
login: user.login
};
}));

if (untilAllLoaded && response.body.length >= 100) {
return Main.loadStargazersFn(stargazers, untilAllLoaded, currentPage + 1, completedFn);
}
}

completedFn(error, {stargazers});
});
},
/**
* <InlineCss> component allows you to write basic CSS for your component. Target
* your component with `&` and its children with `& selectors`. Be specific.
Expand Down Expand Up @@ -96,6 +75,11 @@ const Main = React.createClass({
const avatarSize = 32;
const avatarUrl = (id) => `https://avatars.githubusercontent.com/u/${id}?v=3&s=${avatarSize}`;

/**
* This is a Transmit prop. See end of file.
*/
const stargazers = this.props.stargazers;

return (
<InlineCss stylesheet={Main.css(avatarSize)} namespace="Main">
<a className="github" href={repositoryUrl}>
Expand All @@ -112,7 +96,7 @@ const Main = React.createClass({
<li>React.js + Router on the client and server</li>
<li>React Hot Loader for instant client updates</li>
<li>Babel.js automatically compiles ES6 + ES7</li>
<li>React-async to preload on server to client</li>
<li>React Transmit to preload on server to client</li>
<li>InlineCss-component for styling components</li>
<li>Accessibility hints from react-a11y</li>
</ul>
Expand All @@ -123,7 +107,7 @@ const Main = React.createClass({
<h3>Community</h3>
<p>
<a href={repositoryUrl} title="you here? star us!">
{this.state.stargazers.map((user) => {
{stargazers.map((user) => {
return <img key={user.id} className="avatar" src={avatarUrl(user.id)} title={user.login} alt={user.login} />;
})}
<img className="avatar" src={avatarUrl(0)} alt="you?" />
Expand All @@ -134,4 +118,37 @@ const Main = React.createClass({
}
});

export default Main;
/**
* Use React Transmit to write declarative queries as Promises.
*/
export default Transmit.createContainer(Main, {
queryParams: {
prevStargazers: [],
nextPage: 1,
pagesToFetch: 22
},
queries: {
stargazers (queryParams) {
/**
* Return a Promise of all the stargazers.
*/
return fetch(
`https://api.github.com/repos/RickWong/react-isomorphic-starterkit/stargazers?per_page=100&page=${queryParams.nextPage}`
).then((response) => {
return response.json();
}).then((page) => {
if (!page || !page.length) {
queryParams.pagesToFetch = 0;
return queryParams.prevStargazers;
}

const stargazers = page.map((user) => ({
id: user.id,
login: user.login
}));

return queryParams.prevStargazers.concat(stargazers);
});
}
}
});

0 comments on commit e513d33

Please sign in to comment.