Skip to content

Commit

Permalink
Add playground for React Hot Loader 2
Browse files Browse the repository at this point in the history
  • Loading branch information
gaearon committed Aug 22, 2015
1 parent 3550ec6 commit dbc8587
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 58 deletions.
45 changes: 1 addition & 44 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,4 @@
react-hot-boilerplate
=====================

The minimal dev environment to enable live-editing React components.

### Usage

```
npm install
npm start
open http://localhost:3000
```

Now edit `src/App.js`.
Your changes will appear without reloading the browser like in [this video](http://vimeo.com/100010922).

### Linting

This boilerplate project includes React-friendly ESLint configuration.

```
npm run lint
```

### Using `0.0.0.0` as Host

You may want to change the host in `server.js` and `webpack.config.js` from `localhost` to `0.0.0.0` to allow access from same WiFi network. This is not enabled by default because it is reported to cause problems on Windows. This may also be useful if you're using a VM.

### Missing Features

This boilerplate is purposefully simple to show the minimal configuration for React Hot Loader. For a real project, you'll want to add a separate config for production with hot reloading disabled and minification enabled. You'll also want to add a router, styles and maybe combine dev server with an existing server. This is out of scope of this boilerplate, but you may want to look into [other starter kits](https://github.com/gaearon/react-hot-loader/blob/master/docs/README.md#starter-kits).

### Dependencies

* React
* Webpack
* [webpack-dev-server](https://github.com/webpack/webpack-dev-server)
* [babel-loader](https://github.com/babel/babel-loader)
* [react-hot-loader](https://github.com/gaearon/react-hot-loader)

### Resources

* [Demo video](http://vimeo.com/100010922)
* [react-hot-loader on Github](https://github.com/gaearon/react-hot-loader)
* [Integrating JSX live reload into your workflow](http://gaearon.github.io/react-hot-loader/getstarted/)
* [Troubleshooting guide](https://github.com/gaearon/react-hot-loader/blob/master/docs/Troubleshooting.md)
* Ping dan_abramov on Twitter or #reactjs IRC
This branch is a playground for the future version of React Hot Loader. Right now it doesn't even use it.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,12 @@
"babel-eslint": "^3.1.9",
"babel-loader": "^5.1.2",
"eslint-plugin-react": "^2.3.0",
"react-hot-loader": "^1.2.7",
"react-proxy": "^0.6.3",
"webpack": "^1.9.6",
"webpack-dev-server": "^1.8.2"
},
"dependencies": {
"autobind-decorator": "^1.3.1",
"react": "^0.13.0"
}
}
65 changes: 52 additions & 13 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import React, { Component } from 'react';
import autobind from 'autobind-decorator';
import hot from './hot';

@hot('RendererA')
class RendererA extends Component {
constructor(props) {
super(props);
this.state = { counter: 0 };
setInterval(() => this.tick(), 10);
this.interval = setInterval(() => this.tick(), 1000);
}

tick() {
Expand All @@ -13,20 +16,27 @@ class RendererA extends Component {
});
}

componentWillUnmount() {
clearInterval(this.interval);
}

// Feel free to edit this
render() {
return (
<span style={{ color: 'red' }}>
{this.state.counter}, {this.props.children}
</span>
<div style={{ color: 'green' }}>
<h2>{this.props.children}</h2>
<h3>Renderer own state: {this.state.counter}</h3>
</div>
);
}
}

@hot('RendererB')
class RendererB extends Component {
constructor(props) {
super(props);
this.state = { counter: 0 };
setInterval(() => this.tick(), 10);
this.interval = setInterval(() => this.tick(), 1000);
}

tick() {
Expand All @@ -35,11 +45,17 @@ class RendererB extends Component {
});
}

componentWillUnmount() {
clearInterval(this.interval);
}

// Feel free to edit this
render() {
return (
<span style={{ color: 'green' }}>
{this.state.counter}, {this.props.children}
</span>
<div style={{ color: 'blue' }}>
<h2>{this.props.children}</h2>
<h3>Renderer own state: {this.state.counter}</h3>
</div>
);
}
}
Expand All @@ -49,31 +65,54 @@ function makeSomething(Renderer, speed) {
constructor(props) {
super(props);
this.state = { counter: 0 };
setInterval(() => this.tick(), speed);
}

componentDidMount() {
this.tick();
}

componentWillUnmount() {
clearTimeout(this.timeout);
}

@autobind
tick() {
this.setState({
counter: this.state.counter + 1
}, () => {
this.timeout = setTimeout(this.tick, speed);
});
}

// Feel free to edit this
render() {
return <h1><Renderer>{this.state.counter}</Renderer></h1>;
return (
<div>
<Renderer>HOC state: {this.state.counter}</Renderer>
</div>
);
}
};
}

let Something1 = makeSomething(RendererA, 10);
let Something2 = makeSomething(RendererB, 1000);
let Something1 = hot('makeSomething$Something1')(
// Feel free to edit this
makeSomething(RendererA, 100)
);
let Something2 = hot('makeSomething$Something2')(
// Feel free to edit this
makeSomething(RendererB, 100)
);

@hot('App')
export default class App extends Component {
// Feel free to edit this
render() {
return (
<div>
<Something1 />
<Something2 />
nice
nice ugh
</div>
);
}
Expand Down
29 changes: 29 additions & 0 deletions src/hot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import { createProxy, getForceUpdate } from 'react-proxy';

if (!window.__reactProxies) {
window.__reactProxies = {};
}

const forceUpdate = getForceUpdate(React);

export default function hot(id, ...dependencies) {
id = [id, ...dependencies.map(dep => dep.__proxyId || dep)].join('$$$');

return function (ReactClass) {
if (window.__reactProxies[id]) {
console.info(`updating ${id}`);
const instances = window.__reactProxies[id].update(ReactClass);
requestAnimationFrame(() => {
instances.forEach(forceUpdate);
});
} else {
console.info(`creating ${id}`);
window.__reactProxies[id] = createProxy(ReactClass);
}

let ProxyClass = window.__reactProxies[id].get();
ProxyClass.__proxyId = id;
return ProxyClass;
};
}

0 comments on commit dbc8587

Please sign in to comment.