-
-
Save devan-sisson/5e87aae191be8167467673ead3b2eba9 to your computer and use it in GitHub Desktop.
Mobx with Recompose structure
This file contains 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
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