diff --git a/docs/api/presenter.md b/docs/api/presenter.md index 01592869..60408c9e 100644 --- a/docs/api/presenter.md +++ b/docs/api/presenter.md @@ -60,6 +60,24 @@ planets from the Microcosm instance provided to it via the `repo` prop. This is available as state, which the Presenter can send into a child component. +### Listening to all state changes + +While we do not recommend it for large projects, some times it's simply easier +to subscribe to all repo changes. `viewModel` can also return a function, which +will be called with state: + +```javascript +class PlanetsPresenter extends Presenter { + viewModel(props) { + return state => state + } + + render() { + return
{ this.state.planets.join(', ') }
+ } +} +``` + ## Receiving Intents Though explicit, passing event callbacks down through a deep component diff --git a/src/addons/presenter.js b/src/addons/presenter.js index fc962ccb..1aa76d29 100644 --- a/src/addons/presenter.js +++ b/src/addons/presenter.js @@ -107,7 +107,14 @@ export default class Presenter extends Component { * @private */ _updatePropMap (props) { - this.propMap = this.viewModel(props) + this.propMap = this.viewModel ? this.viewModel(props) : {} + + if (this.repo && this.propMap === this.repo.state) { + console.warn("The view model for this presenter returned repo.state. " + + "This method onlys run when a presenter is given new properties. " + + "If you would like to subscribe to all state changes, return a " + + "function like: `(state) => state`.") + } } /** @@ -125,9 +132,14 @@ export default class Presenter extends Component { * @private */ _getState () { - const nextState = {} const repoState = this._getRepoState() + if (typeof this.propMap === 'function') { + return this.propMap(repoState) + } + + const nextState = {} + for (let key in this.propMap) { const entry = this.propMap[key] diff --git a/test/addons/presenter.test.js b/test/addons/presenter.test.js index e8fd7132..ea92901f 100644 --- a/test/addons/presenter.test.js +++ b/test/addons/presenter.test.js @@ -240,3 +240,37 @@ test('calling setState in setup does not raise a warning', t => { console.restore() }) + +test('warns when setState in setup does not raise a warning', t => { + class MyPresenter extends Presenter { + viewModel() { + return this.repo.state + } + render() { + returnTest
+ } + } + + console.record() + + mount(Test
+ } + } + + const el = mount(