Skip to content

Instantly share code, notes, and snippets.

@dolpen
Created May 31, 2016 10:11
Show Gist options
  • Save dolpen/ca0c5ce6ca3a1473eb8760df115531ff to your computer and use it in GitHub Desktop.
Save dolpen/ca0c5ce6ca3a1473eb8760df115531ff to your computer and use it in GitHub Desktop.
import React from "react";
import ReactDOM from "react-dom";
import {EventEmitter} from "events";
import weapons from "./weapons.json";
class StateContainer {
constructor(initialState, shouldUpdate) {
this.root = undefined;
this.state = initialState;
this.prevState = Object.assign({}, initialState);
this.emitter = new EventEmitter();
this.shouldUpdate = shouldUpdate || ((a, b) => true);
}
register(rootComponent) {
this.root = rootComponent;
this.root.state = this.prevState;
}
// 今はonだけ
on(type, listener) {
// ここの関数合成の筋が悪すぎてしんどい
return this.emitter.on(type, (...args) => {
listener(...args);
this.commit();
});
}
commit() {
if (this.shouldUpdate(this.prevState, this.state))
this.root.setState(this.state);
this.prevState = Object.assign({}, this.state);
}
}
// React.Component 拡張
const ContainerContextTypes = {
container: React.PropTypes.any
};
class ContainerComponent extends React.Component {
static get childContextTypes() {
return ContainerContextTypes;
}
constructor(...args) {
super(...args);
this.props.container.register(this);
}
getChildContext() {
return {
container: this.props.container
};
}
}
class DispatchableComponent extends React.Component {
static get contextTypes() {
return ContainerContextTypes;
}
dispatch(...args) {
const container = this.context.container;
return container.emitter.emit(...args);
}
}
// 実装
class Weapon extends React.Component {
render() {
return (
<li>
{this.props.data.name} ( {this.props.data.sub} / {this.props.data.special} )
</li>
);
}
}
class RootComponent extends ContainerComponent {
constructor(...args) {
super(...args);
}
render() {
const q = this.props.container.state.filterQuery;
const filteredWeapons = weapons.filter(weapon => {
return weapon.name.indexOf(q) > -1
|| weapon.sub.indexOf(q) > -1
|| weapon.special.indexOf(q) > -1;
});
return <App weapons={filteredWeapons}/>
}
}
class App extends DispatchableComponent {
render() {
return (
<div className="weapons">
<input onChange={(ev) => this.dispatch("change-filter-query", ev.target.value)}/>
<ul>
{
this.props.weapons.map(weapon => {
return <Weapon key={weapon.id} data={weapon}/>
})
}
</ul>
</div>
);
}
}
const container = new StateContainer({
filterQuery: ""
}, (nowState, newState) => {
return nowState.filterQuery.length <= newState.filterQuery.length;
});
ReactDOM.render(
<RootComponent container={container}/>,
document.querySelector(".mainContainer")
);
container.on("change-filter-query", (value) => {
container.state.filterQuery = value;
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment