Skip to content
This repository was archived by the owner on Apr 13, 2023. It is now read-only.
This repository was archived by the owner on Apr 13, 2023. It is now read-only.

After a query has resulted in an error, variable updates that should result in an Apollo QueryResult with no errors do not update the QueryResult's error field in componentWillReceiveProps #1749

@benjaminsaurusrex

Description

@benjaminsaurusrex

Actual Result

  • Component mounts using graphql HOC, with a Query that produces an error
  • Update props so that variables passed to the operation options will now result in a query that succeeds with no errors
  • No network request is made, and inside componentWillReceiveProps, the nextProps.data.error is still defined with the previous error

Intended Result

  • Component mounts using graphql HOC, with a Query that produces an error
  • Update props so that variables passed to the operation options will now result in a query that succeeds with no errors
  • Either a network request is made, or the data is returned from the cache such that nextProps.data.error is no longer defined

How am I testing this?

Good question. I have a basic query that requests a field that always succeeds, and another field that fails when included:

// query.gql
query SomeQuery($shouldFail: Boolean!) {
  successField {
    id
  }
  failField @include(if: $shouldFail) {
    id
  }
}

Now for my components. I have 2 components, one that acts as a parent and determines whether its child shouldFail or not so that the child gets prop updates, which trigger a variable update when the operation options are different.

// Child
class ChildPresentation extends React.Component<Props> { ... }

// Child connected to graphql HOC
const Child = graphql(query, {
  options: (props: Props) => ({
    variables: {
      shouldFail: props.shouldFail,
    },
  }),
})(ChildPresentation);

// Parent
class Parent extends React.Component<ParentProps> {
  public render() {
    return <Child shouldFail={this.state.shouldFail} />;
  }
}

With this set up, you can see how Parent can easily update its state, which causes Child's shouldFail prop to update, which causes the variable inside the operation options to update... and down the rabbit hole.

The rabbit hole

When a GraphQL error comes through, the Observable decides to clean itself up.

https://github.com/zenparsing/zen-observable/blob/e924b1ddcde8aaac157cedb1908b2ad83b20e7bc/zen-observable.js#L184

Which removes it from ObservableQuery's list of observers (emptying it).

https://github.com/apollographql/apollo-client/blob/2.0/packages/apollo-client/src/core/ObservableQuery.ts#L538

Then when the new query variables come in, it follows the path of:

Which would normally end up doing the network request, but since earlier the observers list became empty, this ends up being a no-op.

https://github.com/apollographql/apollo-client/blob/2.0/packages/apollo-client/src/core/ObservableQuery.ts#L450

Then there's no recovery from react-apollo's perspective; when the graphql hoc calls subscribeToQuery at the end of componentWillReceiveProps (after the GraphQL.updateQuery above), that's a no-op because from its perspective it thinks it's still subscribed.

https://github.com/apollographql/react-apollo/blob/apollo-client-2.0/src/graphql.tsx#L432


The above was found and documented after some minor digging to see why this was happening.

Repro Environment

I actually don't have an easily accessible repro environment with public data that can be used for this. Though it should be fairly straightforward to set up by following my components above.

Version

  • react-apollo@2.1.0-beta.3
  • apollo-client@2.2.5
  • react@16.2.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    has-PRhas-reproduction❤ Has a reproduction in a codesandbox or single minimal repository

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions