GraphQL is a popular API query language for clients to access data on servers. Cresta uses GraphQL in different ways to act as a bridge between our frontend and backend systems. This blog will discuss how a developer familiar with Redux can migrate over to GraphQL using the popular Apollo Client library to take advantage of GraphQL features.
At Cresta, simplicity and speed are a couple of our core values for our development team. In a typical application with client and server components, client state management is typically different from server state management. For example, it’s popular to use Redux for client state management and REST API for server state manipulation. However, if GraphQL is used for both purposes, we gain greater simplicity.
This guide offers insights and tips for developers like yourself, who have an understanding of Redux using GraphQL and Apollo Client as a client state store. We’ll explore a use case by taking part in an existing redux react chat client and partially converting its message history component while using GraphQL and Apollo Client. Let’s dive in.
Many libraries are available for state management and synchronizing data with the server, so why use GraphQL?
On the one hand, there are Redux, MobX, and so on, which do an excellent job of client state management but leave the server synchronization as a completely separate task to be implemented by you (or by using a library such as Redux-API to ease this implementation).
On the other hand, there are tools like Firebase, Realm Sync, and PouchDB+CouchDB, which abstract and automate database synchronization so that you only need to deal with client data. However, you also loses control of the data synchronization process. The abstraction makes it hard to control what data synchronizes first. It could skip synchronization of non-critical data altogether. Furthermore, this approach locks the application to a specific (and sometimes proprietary) database system.
By using GraphQL, you get a more balanced solution between the two sets of tool types. Because both the client and server speak the same language, synchronization becomes easier, yet you still maintain control. For the client state, you may use a library like Apollo Client. A GraphQL server defines and exposes the Query API layer so that clients can access/save data with it. On the server-side, a variety of choices exist.*
Additionally, it should be noted that GraphQL is an open standard, which prevents vendor lock-in and makes it easier to swap out parts of the system in the future as the application evolves.
As official documentation describes, Apollo Client is a complete state management library with GraphQL. Interestingly, one of its key features is zero-config caching, making it easy to use as a state store. Furthermore, Apollo Client already comes with support for React applications.
Apollo Client is frequently used with a GraphQL backend, so some programmers believe the myth that it can ONLY be used with a GraphQL backend. The truth of the matter is – Apollo Client can absolutely be used as a client-only, in-browser store without any backend. Below is a basic code sample that initiates a client with only in-memory caching, without specifying any GraphQL backend to connect to:
More specifically, in the code example presented above, an in-memory cache is provided to the client to connect to, and the local state can be stored in this cache, according to this Apollo Client Documentation. It’s an easy assumption to make, but Apollo Client can be used either with GraphQL or as an in-browser store without any backend.
To make debugging more manageable, the Apollo Client Devtools may be installed in your Chrome browser to watch queries and client cache state as you debug the code.
Now that we’ve addressed a common myth and have the tools we need, let’s begin the use case example of replacing Redux store with Appollo Client.
Let’s look at one example of a react-redux component to show message history in a redux chat app. Note how react-redux passes state threads into the component as a react props value:
In this example, the threads state contains a dictionary of arrays, with the recipient being the key. Each array contains elements with key (numeric sequence number), from (string identifying the sender) and text (string for the message text) for that recipient.
Examine the screenshot below to see how the new code looks. This shows how you can convert this component using Apollo Graph QL (you can test it here).
The above screenshot shows that by using the Apollo Client useQuery method, the client GraphQL cache can be queried, and the return values can be passed as props to the react UI component to render.
This example is not super helpful, however it does render a static, hardwired state into the UI. To realize the full power of using Apollo Client cache as a store, let’s explore how to modify the stored values in the in-memory cache.
To make modifications to the store Redux, you can use Actions and Reducers. However, when Apollo Client cache is used as a store, the way to make modifications is slightly different:
The above example shows how to access the store, but what about modifying the store when new messages are received? In this Redux example, whenever a new message is received, the reducer code updates this threads Redux state by concatenating the new message to the array corresponding to the recipient. See below:
The corresponding, converted code with Apollo Client is below, and you can test it here.
Note the following:
As shown in the comparison table below, the advantage of using Apollo Client is by simplification – that is, it’s the opportunity to unify usage of GraphQL for both client state store and interactions with backends.
This guide explains how to convert part of a simple, open-source Redux chat app from Redux to Apollo Client. However, you can apply the concepts explained to other Redux applications too.
You can clone the sample converted chat app at this GitHub link. Feel free to clone, modify and experiment.
Below are some next steps to take this to the next level:
Let us know your thoughts and whether you’d like to see more on this topic.
*Examples of GraphQL backends: