From a86d0b5b02db9dd721182f302b594a2e19da3ede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Tue, 2 Apr 2019 13:39:34 +0200 Subject: [PATCH] imp: store connect: mapStateToProps receive ownProps --- src/store.ts | 29 ++++++++++++----------- tests/store.test.ts | 57 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 63 insertions(+), 23 deletions(-) diff --git a/src/store.ts b/src/store.ts index 1bc24d33..93af6529 100644 --- a/src/store.ts +++ b/src/store.ts @@ -7,24 +7,20 @@ export function connect(mapStateToProps) { return class extends Comp { constructor(parent, props?: any) { const env = parent instanceof Component ? parent.env : parent; - const storeProps = mapStateToProps(env.store.state); - props = Object.assign(props || {}, storeProps); - super(parent, props); + const ownProps = Object.assign({}, props || {}); + const storeProps = mapStateToProps(env.store.state, ownProps); + const mergedProps = Object.assign(props || {}, storeProps); + super(parent, mergedProps); this.__widget__.currentStoreProps = storeProps; + this.__widget__.ownProps = ownProps; } mounted() { this.env.store.on("update", this, () => { - const storeProps = mapStateToProps(this.env.store.state); + const ownProps = this.__widget__.ownProps; + const storeProps = mapStateToProps(this.env.store.state, ownProps); if (!shallowEqual(storeProps, this.__widget__.currentStoreProps)) { this.__widget__.currentStoreProps = storeProps; - // probably not optimal, will do 2 object.assign, one here and - // one in updateProps. - const nextProps = Object.assign( - {}, - this.props, - this.__widget__.currentStoreProps - ); - this.updateProps(nextProps, false); + this.updateProps(ownProps, false); } }); super.mounted(); @@ -34,8 +30,13 @@ export function connect(mapStateToProps) { super.willUnmount(); } updateProps(nextProps, forceUpdate) { - nextProps = Object.assign(nextProps, this.__widget__.currentStoreProps); - return super.updateProps(nextProps, forceUpdate); + this.__widget__.ownProps = nextProps; + const mergedProps = Object.assign( + {}, + nextProps, + this.__widget__.currentStoreProps + ); + return super.updateProps(mergedProps, forceUpdate); } }; }; diff --git a/tests/store.test.ts b/tests/store.test.ts index 4fed145c..adbcccb9 100644 --- a/tests/store.test.ts +++ b/tests/store.test.ts @@ -112,13 +112,13 @@ describe("connecting a component to store", () => { class Child extends Component { inlineTemplate = `
`; mounted() { - steps.push('child:mounted'); + steps.push("child:mounted"); } willUnmount() { - steps.push('child:willUnmount') + steps.push("child:willUnmount"); } destroyed() { - steps.push('child:destroyed'); + steps.push("child:destroyed"); } } @@ -142,16 +142,55 @@ describe("connecting a component to store", () => { const parent = new Parent(env); await parent.mount(fixture); - expect(steps).toEqual([ - 'child:mounted', - ]); + expect(steps).toEqual(["child:mounted"]); await parent.updateState({ child: false }); expect(steps).toEqual([ - 'child:mounted', - 'child:willUnmount', - 'child:destroyed', + "child:mounted", + "child:willUnmount", + "child:destroyed" ]); }); + test("connect receives ownprops as second argument", async () => { + const state = { todos: [{ id: 1, text: "jupiler" }] }; + let nextId = 2; + const mutations = { + addTodo(state, text) { + state.todos.push({ text, id: nextId++ }); + } + }; + const store = new Store({ state, mutations }); + + class TodoItem extends Component { + inlineTemplate = ``; + } + const ConnectedTodo = connect((state, props) => { + const todo = state.todos.find(t => t.id === props.id); + return todo; + })(TodoItem); + + class TodoList extends Component { + inlineTemplate = `
+ + + +
`; + widgets = { ConnectedTodo }; + } + + const ConnectedTodoList = connect(state => state)(TodoList); + + (env).store = store; + const app = new ConnectedTodoList(env); + + await app.mount(fixture); + expect(fixture.innerHTML).toBe("
jupiler
"); + + store.commit("addTodo", "hoegaarden"); + await nextTick(); + expect(fixture.innerHTML).toBe( + "
jupilerhoegaarden
" + ); + }); });