james emanon
james emanon

Reputation: 11837

Updating Graphql Tree w/o hitting Back End with Mutation

I am currently using graphql instead of Redux for some state management data sets. I am finding I am using a mutation that is on the server side, but if my UI/frontend only cares about it, why do I have to create a mutation that then hits the server. Is there a way to omit that part and set the graphql data tree with some updates from the frontend/UI only?

This is my mutation

try {
  await updateSomething({
    // front end only cares about these values, but I do 
    // need them across various components etc..
    variables: {
      id,
      name
    },
    update: (store, { data: { someData } }) => {
      const data = store.readQuery({ query: MY_QUERY });
      data.someArray.push(someData);
      store.writeQuery({ query: MY_QUERY, data });
    }
  });
} catch (e) {
 // deal with error
}
  1. I haven't been able to figure out how to update the graphql tree without having to create a resolver on the Backend. So I'm concerned that hitting the backend constantly will incur a performance hit, IF the data I am saving has no care or need for the backend to know about.

Of course, I had to write a mutation on the frontend for this, but also a corresponding mutation/resolver on the backend... BUT, if my data is derived from the front end, and really has no consequence for a database etc... it only really needs to serve as a redux state machine. How can I accomplish this without interacting with a server side mutation/resolver?

Upvotes: 0

Views: 125

Answers (1)

Daniel Rearden
Daniel Rearden

Reputation: 84867

Since it looks like you're already using apollo, you should utilize apollo-link-state. A state link effectively allows you to manage client state through apollo.

Your client set up would look something like this:

import { ApolloClient } from 'apollo-client'
import { ApolloLink } from 'apollo-link'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { HttpLink } from 'apollo-link-http'
import { withClientState } from 'apollo-link-state'

const cache = new InMemoryCache()
const stateLink = withClientState({
  cache,
  resolvers,
  defaults,
})
const client = new ApolloClient({
  cache,
  link: ApolloLink.from([stateLink, new HttpLink()]),
})

The defaults you pass to withClientState define your initial state, while the resolvers object defines behaviors for client-only queries and mutations.

const defaults = { foo: { __typename: 'Foo', bar: 'Bar', } }

const resolvers = {
  Mutation: {
    updateFoo: (_, { bar }, { cache }) => {
      const data = {
        foo: {
          bar,
          __typename: 'Foo'
        }
      }
      cache.writeData({ data })
      return data.foo
    }
  }
}

You can then use the @client directive to identify mutations and queries that should be resolved using the state link:

mutation DoSomething($bar: String) {
  updateFoo(bar: $bar) @client
}

Read the docs for a more complete explanation and great examples.

Upvotes: 1

Related Questions