Skip to content

Instantly share code, notes, and snippets.

@geoffmiller
Last active December 11, 2018 22:20
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save geoffmiller/bbb6cad359ee17421d85445b331c804e to your computer and use it in GitHub Desktop.
Save geoffmiller/bbb6cad359ee17421d85445b331c804e to your computer and use it in GitHub Desktop.
Mobx with Recompose structure
const { compose, mapProps, withHandlers, lifecycle } = Recompose;
const { observable, action } = mobx;
const { inject, observer, Provider } = mobxReact;
const { PropTypes } = React;
// store
// ============================
const counterStore = observable({
// for primitive values, wrap the value inside a observable,
// or wrap it in an plain js object
// REF: https://mobx.js.org/refguide/boxed.html
count: observable(0)
});
// action
// ============================
const counterActions = store => {
const increment = action(() => {
store.count.set(store.count.get() + 1);
});
const decrement = action(() => {
store.count.set(store.count.get() - 1);
});
const init = action(() => {
store.count.set(999);
});
return {
increment,
decrement,
init
};
};
// Stateless component
// ============================
const CounterComponent = ({count, onIncrementClick, onDecrementClick}) => (
<div>
<h1>Count: {count.get()}</h1>
<div>
<button onClick={onIncrementClick}>+</button>
<button onClick={onDecrementClick}>-</button>
</div>
</div>
);
CounterComponent.propTypes = {
count: PropTypes.object.isRequired,
onIncrementClick: PropTypes.func.isRequired,
onDecrementClick: PropTypes.func.isRequired,
onInit: PropTypes.func.isRequired
};
// HOC
// ============================
const mapStoreToProps = ({counterStore}) => {
return {
count: counterStore.count,
actions: counterActions(counterStore)
};
};
const mapActionsToProps = {
onIncrementClick: ({actions}) => () => actions.increment(),
onDecrementClick: ({actions}) => () => actions.decrement(),
onInit: ({actions}) => () => actions.init(),
};
const CounterHOC = compose(
inject('counterStore'),
withProps(mapStoreToProps),
withHandlers(mapActionsToProps),
lifecycle({
componentDidMount() {
// the context(this) will be converted to
// the base component by recompose
this.props.onInit();
}
}),
observer
)(CounterComponent);
// app.js
// ============================
ReactDOM.render(
<Provider counterStore={counterStore}>
<CounterHOC />
</Provider>,
document.getElementById('container')
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment