Skip to content

Instantly share code, notes, and snippets.

@reneviering
Last active October 22, 2017 08:34
Show Gist options
  • Save reneviering/4e98674df45843e85540b646b80b8501 to your computer and use it in GitHub Desktop.
Save reneviering/4e98674df45843e85540b646b80b8501 to your computer and use it in GitHub Desktop.
Simple Domain Object to hold simple application state in react.
// Higher order component to connect the Domain to the component
const connectDomainToComponent = (WrappedComponent, Domain) => {
return class extends React.Component {
constructor() {
super();
this.domain = new Domain();
if (typeof(this.domain.getState) !== 'function') throw new Error('There is no function getState(…)')
const initialState = this.domain.getState();
if (typeof(initialState) !== 'object') throw new Error('The domain state has to be an object');
this.state = initialState;
}
update = (newDomainObject) => {
if (typeof(newDomainObject.then) === 'function') {
newDomainObject.then(newDomainObjectResult => {
this.domain = newDomainObjectResult;
if(typeof(newDomainObjectResult.getState) !== 'function') {
throw new Error('Looks like your domain type is not immutable. Make it immutable or ¯\_(ツ)_/¯')
}
this.setState(newDomainObjectResult.getState());
})
} else {
this.domain = newDomainObject;
if(typeof(newDomainObject.getState) !== 'function') {
throw new Error('Looks like your domain type is not immutable. Make it immutable or ¯\_(ツ)_/¯')
}
this.setState(newDomainObject.getState());
}
}
render() {
return <WrappedComponent domain={this.domain} update={this.update} {...this.state} />
}
};
};
// Counter-Domain
class Counter {
constructor(count = 0) {
this.state = { count };
}
getState() {
return this.state;
}
increment() {
return new Counter(this.state.count + 1);
}
decrement() {
return new Counter(this.state.count - 1);
}
}
class App extends React.Component {
constructor() {
super();
}
componentDidMount() {
}
handleIncrement = () => {
this.props.update(this.props.domain.increment());
}
handleDecrement = () => {
this.props.update(this.props.domain.decrement());
}
render() {
return (
<div>
<p>{this.props.count}</p>
<button onClick={this.handleIncrement}>Increment</button>
<button onClick={this.handleDecrement}>Decrement</button>
</div>
);
}
}
const AppWithDomain = connectDomainToComponent(App, Counter);
ReactDOM.render(
<AppWithDomain/>,
document.getElementById('app')
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment