question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Local state resolvers with reactive data

See original GitHub issue

Hi 👋

I’m playing around with Apollo’s Local State Management feature and I found a strange behaviour that has not been made clear in the documentation. Could you help me understand if this is a bug, or if it’s by design and if there’s a workaround?

Here it is:

  • I have an Apollo Server with these typeDefs:
  type Query {
    greetings: [Greeting]
  }

  type Greeting {
    word: String
  }
  • the Apollo client is set with a local resolver and a local state:
const client = new ApolloClient({
  // ...
  defaultOptions: {
    query: {
      fetchPolicy: "network-only"
    },
  },
  resolvers: {
    Greeting: {
      name: (parent, args, { client }) => {
        const state = client.readQuery({
          query: gql`
            query StateQuery {
              localState {
                value
              }
            }
          `
        });

        return state.localState.value;
      }
    }
  }
});

client.writeData({
  data: {
    localState: {
      __typename: "LocalState",
      value: "John"
    }
  }
});

With this setup, everything is ok on the first query with react-apollo hook:

const { data } = useQuery(gql`
  query ComponentQuery {
    localState @client {
      value
    }
    greetings {
      name @client(always: true)
      word
    }
  }
`);

console.log(data);
/* {
  "localState": {
    "value": "John",
    "__typename": "LocalState"
  },
  "greetings": [
    {
      "name": "John",
      "word": "Hello",
      "__typename": "Greeting"
    },
    {
      "name": "John",
      "word": "Welcome",
      "__typename": "Greeting"
    }
  ]
} */

But when I update the local state with:

client.writeQuery({
  query: STATE_QUERY,
  data: {
    localState: { __typename: "LocalState", value: "Foo" }
  }
});

The previous query is correctly re-run, but the local field name has not been updated:

console.log(data);
/* {
  "localState": {
    "value": "Foo",
    "__typename": "LocalState"
  },
  "greetings": [
    {
      "name": "John",
      "word": "Hello",
      "__typename": "Greeting"
    },
    {
      "name": "John",
      "word": "Welcome",
      "__typename": "Greeting"
    }
  ]
} */

You can find a Sandbox set up here: https://codesandbox.io/s/apollo-local-state-management-5dy2f?fontsize=14&module=%2Fsrc%2FApolloProvider.tsx

Is it intended? Do you plan on supporting this kind of feature?

Thank you for your help!

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:12 (5 by maintainers)

github_iconTop GitHub Comments

3reactions
dcecilecommented, Nov 18, 2019

@freshollie OK I understand now, thanks 🙏

I’d be nice if Apollo treated readQuery inside of a local resolver as a “watch query”, just like useQuery inside of React component.

My feature request is if the source of readQuery changes and the local resolver is still in use by some React component’s useQuery, then the local resolver would automatically re-run and its results get sent to the React component.

This way I wouldn’t need to do all of the bookkeeping and updating myself (i.e. which React components are active, which fragments they use, which local resolvers of those fragments are used, and how to recalculate the results of all those local resolvers).

3reactions
fresholliecommented, Nov 17, 2019

@dcecile Please see: https://codesandbox.io/s/apollo-local-state-management-zrwel

The writeQuery should not only update the localState, but also update all greetings objects in the cache in order to achieve the desired effect.

The reason the @client(always: true) doesn’t work is because the overall greetings query has already been cached, so any subsequent queries are not going to execute the name resolver.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Local resolvers - Apollo GraphQL Docs
Manage local data with GraphQL like resolvers. ... Apollo Client (>= 2.5) has built-in local state handling capabilities that allow you to store...
Read more >
Storing local data with Apollo Client | by Eugenia Zigisova
Local state using Reactive Variables … and Apollo Cache. Reactive variables are containers for saving, retrieving, and modifying data.
Read more >
Local-only fields - Client (React) - Apollo GraphQL Docs
Storing local state in reactive variables · You can read and modify reactive variables from anywhere in your application, without needing to use...
Read more >
Deconstructing Apollo Part 3: Reactive Variables · Blog
Local resolvers offered a way to store additional data in the client ... reactive variables, you can elegantly add pieces of local state...
Read more >
Migrating to Apollo Client 3 - Part 2: local state | JG Tech Blog
This reactive variable can be read and modified from anywhere in your application and doesn't enforce data normalisation, so it's now easier to ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found