diff --git a/Changelog.md b/Changelog.md index 51800fd82f..e8dd1eccfa 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,10 @@ Expect active development and potentially significant breaking changes in the `0 ### vNext +### v0.5.4 + +- Bug: Created better reference to updateQuery when bound early. It will also throw if called before it should be. + ### v0.5.3 - Bug: Fixed issue with updateQuery not being present during componentWillMount [#203](https://github.com/apollostack/react-apollo/pull/203) diff --git a/package.json b/package.json index 2ebafd2d55..4bafc971d0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-apollo", - "version": "0.5.3", + "version": "0.5.4", "description": "React data container for Apollo Client", "main": "index.js", "scripts": { diff --git a/src/graphql.tsx b/src/graphql.tsx index 0dec2c96c0..5f3ca1bf4c 100644 --- a/src/graphql.tsx +++ b/src/graphql.tsx @@ -253,7 +253,6 @@ export default function graphql( // request / action storage private queryObservable: ObservableQuery | Object; private querySubscription: Subscription | Object; - private updateQueryMethod: any; // calculated switches to control rerenders private haveOwnPropsChanged: boolean; @@ -352,7 +351,14 @@ export default function graphql( }; // XXX type this better - queryData.updateQuery = (mapFn: any) => this.updateQueryMethod = mapFn; + // this is a stub for early binding of updateQuery before data + queryData.updateQuery = (mapFn: any) => { + invariant(!!(this.queryObservable as ObservableQuery).updateQuery, ` + Update query has been called before query has been created + `); + + (this.queryObservable as ObservableQuery).updateQuery(mapFn); + }; if (!forceFetch) { try { @@ -421,9 +427,6 @@ export default function graphql( const observableQuery = watchQuery(queryOptions); const { queryId } = observableQuery; - // bind any eariler set updateQuery method - if (this.updateQueryMethod) observableQuery.updateQuery(this.updateQueryMethod); - // the shape of the query has changed if (previousQuery.queryId && previousQuery.queryId !== queryId) { this.data = assign(this.data, { loading: true }); diff --git a/test/react-web/client/graphql/queries.tsx b/test/react-web/client/graphql/queries.tsx index 9097134288..5b5c0f5e73 100644 --- a/test/react-web/client/graphql/queries.tsx +++ b/test/react-web/client/graphql/queries.tsx @@ -1184,7 +1184,6 @@ describe('queries', () => { componentWillMount() { // tslint:disable-line expect(this.props.data.updateQuery).to.be.exist; expect(this.props.data.updateQuery).to.be.instanceof(Function); - expect(this.props.data.updateQuery).to.not.throw; done(); } render() { @@ -1195,6 +1194,70 @@ describe('queries', () => { mount(); }); + it('updateQuery throws if called before data has returned', (done) => { + const query = gql`query people { allPeople(first: 1) { people { name } } }`; + const data = { allPeople: { people: [ { name: 'Luke Skywalker' } ] } }; + const networkInterface = mockNetworkInterface({ request: { query }, result: { data } }); + const client = new ApolloClient({ networkInterface }); + + @graphql(query) + class Container extends React.Component { + componentWillMount() { // tslint:disable-line + expect(this.props.data.updateQuery).to.be.exist; + expect(this.props.data.updateQuery).to.be.instanceof(Function); + try { + this.props.data.updateQuery(); + done(new Error('should have thrown')) + } catch (e) { + expect(e).to.match(/Invariant Violation:/); + done(); + } + } + render() { + return null; + } + }; + + mount(); + }); + + it('allows updating query results after query has finished (early binding)', (done) => { + const query = gql`query people { allPeople(first: 1) { people { name } } }`; + const data = { allPeople: { people: [ { name: 'Luke Skywalker' } ] } }; + const data2 = { allPeople: { people: [ { name: 'Leia Skywalker' } ] } }; + const networkInterface = mockNetworkInterface( + { request: { query }, result: { data } }, + { request: { query }, result: { data: data2 } } + ); + const client = new ApolloClient({ networkInterface }); + + let isUpdated; + @graphql(query) + class Container extends React.Component { + public updateQuery: any; + componentWillMount() { + this.updateQuery = this.props.data.updateQuery; + } + componentWillReceiveProps(props) { + if (isUpdated) { + expect(props.data.allPeople).to.deep.equal(data2.allPeople); + done(); + return; + } else { + isUpdated = true; + this.updateQuery((prev) => { + return data2; + }); + } + } + render() { + return null; + } + }; + + mount(); + }); + it('allows updating query results after query has finished', (done) => { const query = gql`query people { allPeople(first: 1) { people { name } } }`; const data = { allPeople: { people: [ { name: 'Luke Skywalker' } ] } };