diff --git a/package.json b/package.json index 24130191af..ceede22b59 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "apollo-client": "^0.4.0" }, "devDependencies": { - "apollo-client": "^0.4.0", + "apollo-client": "^0.4.11", "babel-jest": "^14.1.0", "babel-preset-react-native": "^1.9.0", "browserify": "^13.0.0", diff --git a/src/graphql.tsx b/src/graphql.tsx index 392dd0ecb6..18d521b2fc 100644 --- a/src/graphql.tsx +++ b/src/graphql.tsx @@ -416,6 +416,7 @@ export default function graphql( fetchMore, startPolling, stopPolling, + updateQuery, oldData = {}; const next = ({ data = oldData, loading, error }: any) => { @@ -429,13 +430,14 @@ export default function graphql( 'refetch' in data || 'fetchMore' in data || 'startPolling' in data || - 'stopPolling' in data + 'stopPolling' in data || + 'updateQuery' in data ); invariant(!resultKeyConflict, `the result of the '${graphQLDisplayName}' operation contains keys that ` + `conflict with the return object. 'errors', 'loading', ` + - `'startPolling', 'stopPolling', 'fetchMore', and 'refetch' cannot be ` + + `'startPolling', 'stopPolling', 'fetchMore', 'updateQuery', and 'refetch' cannot be ` + `returned keys` ); @@ -453,6 +455,7 @@ export default function graphql( startPolling, stopPolling, fetchMore, + updateQuery, error, }, data); @@ -499,10 +502,11 @@ export default function graphql( fetchMore = createBoundRefetch((this.queryObservable as any).fetchMore); startPolling = (this.queryObservable as any).startPolling; stopPolling = (this.queryObservable as any).stopPolling; + updateQuery = (this.queryObservable as any).updateQuery; // XXX the tests seem to be keeping the error around? delete this.data.error; - this.data = assign(this.data, { refetch, startPolling, stopPolling, fetchMore, variables }); + this.data = assign(this.data, { refetch, startPolling, stopPolling, updateQuery, fetchMore, variables }); } forceRenderChildren() { diff --git a/test/react-web/client/graphql/queries.tsx b/test/react-web/client/graphql/queries.tsx index 040e46c114..d8bfd866e2 100644 --- a/test/react-web/client/graphql/queries.tsx +++ b/test/react-web/client/graphql/queries.tsx @@ -657,6 +657,28 @@ describe('queries', () => { mount(); }); + it('exposes updateQuery as part of the props api', (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 { + componentWillReceiveProps({ data }) { // tslint:disable-line + expect(data.updateQuery).to.be.exist; + expect(data.updateQuery).to.be.instanceof(Function); + expect(data.updateQuery).to.not.throw; + done(); + } + render() { + return null; + } + }; + + mount(); + }); + it('resets the loading state after a refetched query', (done) => { const query = gql`query people { allPeople(first: 1) { people { name } } }`; @@ -829,4 +851,39 @@ describe('queries', () => { 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' } ] } }; + 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 { + componentWillReceiveProps(props) { + if (isUpdated) { + expect(props.data.allPeople).to.deep.equal(data2.allPeople); + done(); + return; + } + else { + isUpdated = true; + props.data.updateQuery((prev) => { + return data2; + }); + } + } + render() { + return null; + } + }; + + mount(); + }); + });