Created
December 18, 2014 16:36
-
-
Save seanhess/b8ada5fe0e1ae85be5ff to your computer and use it in GitHub Desktop.
Omniscient React Router
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>React Omniscient</title> | |
</head> | |
<body> | |
<div id="content"></div> | |
<script src="bundle.js"></script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var React = require('react') | |
var immstruct = require('immstruct') | |
var Immutable = require('immutable') | |
var component = require('omniscient') | |
var Router = require('react-router') | |
var axios = require('axios') | |
var {Route, DefaultRoute, Link, RouteHandler} = Router | |
// KNOWN ISSUES: | |
// I have to use React components as page handlers to be able to grab a cursor from the state. I don't want to pass the same cursor to every single page. They might use very different data, or get it from different immstruct objects | |
// I have to use React components as page handlers to get access to the lifecycle methods (not React-Router's fault, really, but I can get it much cleaner with page.js. It would be nice if there was some way to give Router a function to call when the url was hit, which returned a render function or another component that could be called to render | |
// Loading ajax: componentWillReceiveProps gets called over and over again as the request finishes and updates the state. Is there a correct way to do this? | |
// STATE ---------------------------------------------------- | |
var state = immstruct({ | |
greeting: {message:'Hello there!'}, | |
info: {}, | |
}) | |
// WELCOME PAGE -------------------------------------------- | |
var WelcomePage = React.createClass({ | |
// I want to select a particular cursor for this component | |
// note that it might even be from another immstruct! | |
render: function() { | |
return <Welcome greeting={state.cursor('greeting')} /> | |
}, | |
}) | |
var Welcome = component(function({greeting}) { | |
function onChange(e) { | |
greeting.update('message', () => e.target.value) | |
} | |
return <div> | |
<div>{greeting.get('message')}</div> | |
<div><input type="text" value={greeting.get('message')} onChange={onChange}/></div> | |
</div> | |
}).jsx | |
// INFO PAGE --------------------------------------------- | |
var InfoPage = React.createClass({ | |
mixins: [Router.State], | |
// I want to load some ajax data when this page is loaded | |
// is this the correct pattern for react router? | |
load: function() { | |
loadInfo(this.getParams().id) | |
.then(function(info) { | |
state.cursor('info').update(() => Immutable.fromJS(info)) | |
}) | |
}, | |
componentWillMount: function() { | |
this.load() | |
}, | |
// this gets called over and over again, once the request finishes it updates the state | |
// which causes this to get called again | |
componentWillReceiveProps: function() { | |
this.load() | |
}, | |
render: function() { | |
return <Info info={state.cursor('info')}/> | |
}, | |
}) | |
// This is my real component | |
var Info = component(function({info}) { | |
return <div>Current Time is: {info.get('test')}</div> | |
}).jsx | |
// ROOT COMPONENT -------------------------------------------o | |
// The Root Component. When I tried changing this to omniscient, RouteHandler didn't change | |
var App = React.createClass({ | |
render: function () { | |
return ( | |
<div> | |
<header> | |
<ul> | |
<li><Link to="app">WElcome</Link></li> | |
<li><a href="#info/woot">Info Woot</a></li> | |
<li><a href="#info/boot">Info Boot</a></li> | |
</ul> | |
</header> | |
<RouteHandler/> | |
</div> | |
); | |
} | |
}); | |
// ROUTES ------------------------------------------------ | |
var routes = ( | |
<Route name="app" path="/" handler={App}> | |
<Route name="info" path="/info/:id" handler={InfoPage}/> | |
<DefaultRoute handler={WelcomePage}/> | |
</Route> | |
); | |
var Handler; | |
Router.run(routes, function (h) { | |
Handler = h | |
render() | |
}); | |
function render () { | |
if (!Handler) return | |
React.render(<Handler/>, document.querySelector("#content")); | |
} | |
render() | |
state.on('swap', render); | |
// AJAX ----------------------------------------------------- | |
// Example AJAX call, just returns {test:<id>} | |
function loadInfo(id) { | |
return axios.get('http://echo.jsontest.com/test/' + id) | |
.then((rs) => rs.data) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "react-omniscient", | |
"version": "1.0.0", | |
"description": "", | |
"main": "index.js", | |
"scripts": { | |
"test": "echo \"Error: no test specified\" && exit 1" | |
}, | |
"author": "", | |
"license": "ISC", | |
"dependencies": { | |
"axios": "0.4.2", | |
"immstruct": "1.2.1", | |
"immutable": "3.4.0", | |
"omniscient": "2.0.1", | |
"react": "0.12.1", | |
"react-router": "0.11.6" | |
}, | |
"devDependencies": { | |
"jsx-loader": "0.12.2", | |
"webpack": "1.4.13" | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module.exports = { | |
entry: './index.jsx', | |
output: { | |
path: './', | |
filename: 'bundle.js' | |
}, | |
resolve: { | |
extensions: ['', '.js', '.json', '.jsx', 'index.jsx', 'index.js', '.styl'] | |
}, | |
module: { | |
loaders: [ | |
{ test: /\.jsx?$/, loader: 'jsx-loader?harmony'}, | |
] | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment