Managing Local State with Apollo Client

Andrico Karoulla
ITNEXT
Published in
8 min readMay 2, 2018

--

Prologue

One of Web Development’s biggest strengths and weaknesses is its approach to modularity. A key programming mantra is to choose something (a function, a package) to do a single job and to do it well. The downside to this approach can mean a single project can be juggling between dozens of separate technologies and concepts, each focusing on something specific.

So choosing Apollo Client to handle my local state as well my remote data seems like a no brainer. Why deal with Redux’s boilerplate and idioms when I’ve already got Apollo/GraphQL set up to get data from my backend?

While this article is going to deal with setting up Apollo to handle local state, it’s not going to be an introduction to the tech. (This legit howtographql tutorial is a good shout for that).

Note: The finished repo can be found here. As well as providing you with help if you get stuck, it also acts as a React app set up with Apollo-Client for local state functionality out of the box to get you on your way.

Vincent Vega & Marsellus Wallace’s Wife

We’ll start by cloning the corresponding repo from here. This repo contains a simple react website, with a sidebar, header and a body. It’s pretty static in nature, no dynamic content (..yet). By the end of this tutorial we’ll have Apollo managing the state of the website. Clicking an item in the sidebar will change the state of the website, which in turn updates the header to display the new data.

If you check package.json you’ll see that we’ve only got the basics, plus some additional packages pertaining to our parcel setup.

After cloning the repo run your standard commands

> yarn
> yarn dev

to install all of your packages and to whip up a local server. Go to localhost:1234 and you’ll hopefully see the demo website in all of its glory. It’s static right now, so clicking around won’t do a thing.

What we want to do first and foremost is to get Apollo in our project, so install these packages. apollo-client lets us configure our instance of Apollo, and react-apollo is the driver that allows us to integrate it in our react application. Due to an issue with parcel (I think) we’ll also need to install graphql.

> yarn add apollo-client react-apollo graphql

so create a new directory src/apollo. Crack open an index.jsfile and add the following

src/apollo/index.js

This is initialising our Apollo Client which we will then use to wrap our React application by adding the following inside of our src/index.js file.

src/index.js

We now have Apollo ready to use in our app. Everything builds when we restart our dev server, but we get an error when we try and access it in the browser. The console will tell us that we need to specify the link and cache properties for our Apollo client, so let’s do that.

> yarn add apollo-link apollo-cache-inmemory apollo-link-state

The previous line adds the new Apollo dependencies to our application while the following code resolves the console errors we were getting. So go back apollo/index.jsand update it so the file looks like this:

src/apollo/index.js

Let’s create an instance of our cache. The cache is Apollo’s normalised data store that stores the results of the query into a flattened data structure. (why does this benefit us?). We will read from the cache when we make our graphql query, and we’ll write to the cache when we make our mutation resolver.

You can see we’ve also added link to our client object. The ApolloLink.from()method lets us modularly configure how our queries are sent over HTTP. We can use this to handle errors, authorisation and provide access to our backend. We’re not going to be doing any of this for the sake of the tutorial but we will set up our client state here. So we create const stateLinkabove and pass in our cache. We’ll add our default state and resolvers here later.

Going back to the browser, you’ll see our lovely static site displaying in all of its magnificence. Let’s add some default state to our project and fire off our first query.

Inside of the apollo directory create a new directory called defaults and add an index.jsinside of it. The file will contain the following:

src/defaults/index.js

We create an object which acts as the default state of our site, apolloClientDemo is the name of the data structure we want to access when we make our queries. The __typename is the mandatory identifier that our cache uses, and the currentPageName is the specific item of data that our header will use to * you guessed it * display the current page name.

We’ll need to add this to our apollo/index.js file

src/apollo/index.js

Let’s clear this up a little bit. Normally import default is the JavaScript keyword you would use to import the code you export default -ed from a file, but coincidentally the name of the object we’re exporting from ./defaults is called defaults . Treat this import line as if it was just any regular ol’ named import.

With that out of the way, let’s go make a query!

The Gold Watch

Add the following package to your project

> yarn add graphql-tag

and create a new directory src/graphqland in there create two new files, index.js and getPageName.js. The graphql directory will house all the queries and mutations. We’ll create our query in getPageName.js by writing the following:

src/graphql/getPageName.js

So we’re exporting two variables, the query and the options. If you’ve used graphql before then the query will look familiar. We’re querying against the apolloClientDemo data structure, retrieving back nothing more than the currentPageName. You’ll notice that we’ve added the @client directive to our query. This tells Apollo to query our local state instead of sending the request to the backend.

Below you’ll see that we’re exporting some options. This is simply defining how we want the data to look when we map the results to the props. We’re destructuring the graphql response and sending it to our view so it looks like this:

props: {
currentPageName: ‘Apollo Demo’,
}
// and not thisprops: {
data: {
apolloClientDemo: {
currentPageName: ‘Apollo Demo’,
}
}
}

Go to the graphql/index.js file and export the query as follows

src/graphql/index.js

Again while this isn’t completely necessary for a small demo/project this file is handy should your application grow larger. Having your queries exported from a single centralised location keeps everything organised and scalable.

Add to your Header.js:

src/components/Header.js

This will now dynamically display the title of the current page. Right now, it will only display the default value, since we haven’t added in our mutation yet. But you can change whatever’s in the default state and the website will reflect that.

Now all that’s left to do is mutate the data in the Apollo cache based by clicking on the sidebar item.

A refreshing image to break up the text. Jeff Sheldon

Jules, Vincent, Jimmie & The Wolf

Things get a little more complicated when dealing with mutations. We no longer just retrieve data from the Apollo store but we update it too. The architecture of mutation is as follows:

> User clicks sidebar item

> Sends variable to mutation

> Fires mutation with variable

> Gets sent to the instance of Apollo

> Finds corresponding resolver

> Applies logic to the Apollo store

> Sends data back to header

If that’s difficult to remember, then use this handy mnemonic created using a mnemonic generator: Urban Senile Fauns Groped Faithless Aslan Solemnly. (easy…)

Start by creating a filegraphql/updatePageName.js.

src/graphql/updatePageName.js

and export it just like we did with the query.

src/graphql/index.js

You’ll notice a few differences regarding the mutation. First off we’ve changed the keyword from query to mutation. This lets graphql know the type of action we’re performing. We’re also defining the name of the query and adding types to the variables we’re passing in. Inside of here we’re specifying the name of the resolver we’ll be using to carry out the changes. We’re also passing through the variable and adding the @client directive.

Unlike the query, we can’t just add the mutation to our view and expect anything to happen. We’ll have to go back to our Apollo directory and add our resolvers. So go ahead and create a new directory apollo/resolvers, and files index.js and updatePageName.js. Inside of updatePageName.jsadd the following:

src/apollo/resolvers/updatePageName.js

Oh my, there’s a lot of interesting things going on in this file. Fortunately, it’s all very logical and doesn’t add many new concepts to what we’ve done before.

So by default when a resolver gets called Apollo passes in all of the variables and the cache. The first argument is a simple ‘_’ because we don’t need to use it. The second argument is the variables object, and the final argument is the cache.

Before we can make changes to the Apollo store, we’ll need to retrieve it. So we make a simple request to get the current content from the store and assign it to previousState. Inside of the data variable, we create a new object with the new information we want to add to the store, which we then write to. You can see that we’ve spread the previous state inside of this object. This is so only the data we explicitly want to change gets updated, everything else remains as it is, this prevents Apollo from needlessly updating components whose data hasn’t changed.

Note: while this isn’t completely necessary for this example, it’s super useful when queries and mutations handle larger amounts of data, so I’ve kept it in for the sake of scalability.

Meanwhile in the resolvers/index.js file…

src/apollo/resolvers/index.js

This is the shape of object that Apollo expects when we pass in our resolvers in to stateLink back in apollo/index.js:

src/apollo/index.js

All that’s left to do is add the mutation to our sidebar component.

src/components/Sidebar.js

Like our resolver file there’s a lot going on in this file, but it’s nothing we haven’t seen before. We import our mutation, use the compose method to add the graphQL mutation to our props. Which we then fire inside of handleClick. We pass in the new name of the page via the <li>element and if everything works, you should be able to run your dev server and click the sidebar items.

Epilogue

Hooray! Hopefully everything worked out. If you got stuck then check out the repo here. It contains all of the finished code. If you’re thinking of using local state management in your next React app then you can fork this repo and continue from there.

There’s a lot more I wanted to cover in this tutorial, such as async resolvers (think Redux thunk), type checking/creating a schema and more fun with the cache.

I really hope that this tutorial was useful for you, I’d like to shout out Sara Vieira’s youtube tutorial too, as it helped me get my head around Apollo Client. If I haven’t done my job well enough by leaving you scratching your head, then follow the link. And finally, feel free to hit me up on social media, I’m a big music and tech fan so talk geek to me.

Thanks for reading!

If you’re interested in hosting me at a conference, meetup or as a speaking guest for any engagement then you can DM me on twitter!

I hope this article taught you something new. I post regularly, so if you want to keep up to date with my latest releases then you can follow me. And remember, the longer you hold the clap button, the more claps you can give. 👏👏👏

You can also check out my other articles below:

Add a touch of Suspense to your web app with React.lazy()

How to use Apollo’s brand new Query components to manage local state

No need to wait for the holidays, start Decorating now

Managing local state with Apollo and Higher Order Components

The React Conference drinking game

Develop and Deploy your own React monorepo app in under 2 hours, using Lerna, Travis and Now

--

--

Hey, I'm @andricokaroulla, Software Developer, and creator of Component Odyssey