apollo-client, react-apollo, and graphql-tag formed the original modular stack for integrating GraphQL into React applications. apollo-client handled caching and network requests, react-apollo provided React-specific hooks and components, and graphql-tag parsed GraphQL query strings. However, the ecosystem has consolidated. apollo-client and react-apollo are now deprecated in favor of @apollo/client, which combines both into a single package. graphql-tag remains a valid utility but is often bundled within the new client.
For years, building GraphQL apps in React meant installing multiple packages: apollo-client for logic, react-apollo for UI bindings, and graphql-tag for query parsing. This modular approach gave developers control but added complexity. Today, the ecosystem has shifted toward consolidation. Let's break down what each package did, why they changed, and what you should use now.
apollo-client was the core engine.
// apollo-client: Legacy setup
import ApolloClient from 'apollo-client';
import { HttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
const client = new ApolloClient({
link: new HttpLink({ uri: '/graphql' }),
cache: new InMemoryCache()
});
react-apollo was the bridge to React.
graphql() and later Hooks like useQuery.apollo-client to work.// react-apollo: Legacy React binding
import { ApolloProvider } from 'react-apollo';
import { useQuery } from 'react-apollo';
function App() {
return (
<ApolloProvider client={client}>
<Dashboard />
</ApolloProvider>
);
}
@apollo/client (The Modern Standard) combines both.
// @apollo/client: Modern unified setup
import { ApolloClient, InMemoryCache, ApolloProvider, useQuery } from '@apollo/client';
const client = new ApolloClient({
uri: '/graphql',
cache: new InMemoryCache()
});
function App() {
return (
<ApolloProvider client={client}>
<Dashboard />
</ApolloProvider>
);
}
graphql-tag is a standalone parser.
// graphql-tag: Standalone usage
import gql from 'graphql-tag';
const GET_USER = gql`
query GetUser($id: ID!) {
user(id: $id) { name }
}
`;
@apollo/client includes gql by default.
gql directly from the main package.package.json.// @apollo/client: Built-in gql tag
import { gql } from '@apollo/client';
const GET_USER = gql`
query GetUser($id: ID!) {
user(id: $id) { name }
}
`;
This is the most critical part of the comparison. The maintainers have made clear decisions about the future of these libraries.
| Package | Status | Recommendation |
|---|---|---|
apollo-client | 🔴 Deprecated | Do not use. Migrate to @apollo/client. |
react-apollo | 🔴 Deprecated | Do not use. Hooks are now in @apollo/client. |
graphql-tag | 🟢 Maintained | Optional. Only needed if not using @apollo/client. |
Maintaining separate packages caused version mismatches.
apollo-client and react-apollo.If you are currently using the legacy stack, here is how the code changes.
Old Way (apollo-client + react-apollo)
import ApolloClient from 'apollo-client';
import { ApolloProvider, useQuery } from 'react-apollo';
import gql from 'graphql-tag';
New Way (@apollo/client)
import { ApolloClient, ApolloProvider, useQuery, gql } from '@apollo/client';
Old Way
// Required separate link and cache packages
import { createHttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
const client = new ApolloClient({
link: createHttpLink({ uri: '/graphql' }),
cache: new InMemoryCache()
});
New Way
// Links and cache are built-in
import { HttpLink, InMemoryCache } from '@apollo/client';
const client = new ApolloClient({
link: new HttpLink({ uri: '/graphql' }),
cache: new InMemoryCache()
});
graphql-tag?There are rare cases where you might still install graphql-tag separately:
urql or graphql-request) but still want the gql tag utility.graphql-tag loader for query extraction.// Example: Using graphql-tag with a different client
import gql from 'graphql-tag';
import { request } from 'graphql-request';
const query = gql`{ posts { title } }`;
request('/api/graphql', query);
apollo-client and react-apollo are history.
They served the community well during the early days of GraphQL in React. However, they are no longer the standard. Continuing to use them introduces technical debt and security risks due to lack of updates.
@apollo/client is the present and future.
It offers the same features with less setup. It is actively maintained, better documented, and designed for modern React patterns like Hooks.
graphql-tag is a utility.
Keep it in your toolkit for non-Apollo tasks, but don't install it unnecessarily if you are already using @apollo/client.
| Task | Legacy Packages | Modern Package |
|---|---|---|
| Create Client | apollo-client | @apollo/client |
| React Hooks | react-apollo | @apollo/client |
| Parse Queries | graphql-tag | @apollo/client (includes gql) |
| Cache Config | apollo-cache-inmemory | @apollo/client |
| Network Links | apollo-link-http | @apollo/client |
For any new project, start with @apollo/client.
It removes the guesswork of compatibility and gives you a single source of truth for your GraphQL layer.
If you are maintaining an old app, plan a migration to the unified package as soon as possible to ensure long-term stability.
Do not choose apollo-client for new projects. It is officially deprecated and no longer receives feature updates. The functionality has been merged into @apollo/client. Only use this if you are maintaining a legacy application that cannot be migrated yet.
Choose graphql-tag if you need to parse GraphQL template literals outside of the Apollo ecosystem or if your build setup requires explicit tagging of queries. However, note that @apollo/client now includes this functionality by default, so you often do not need to install it separately anymore.
Do not choose react-apollo for new projects. It is officially deprecated. All React hooks (like useQuery) and components (like Query) are now built directly into @apollo/client. Migrating to the unified package reduces dependency complexity and ensures long-term support.
Apollo Client is a fully-featured caching GraphQL client with integrations for React, Angular, and more. It allows you to easily build UI components that fetch data via GraphQL. To get the most value out of apollo-client, you should use it with one of its view layer integrations.
To get started with the React integration, go to our React Apollo documentation website.
Apollo Client also has view layer integrations for all the popular frontend frameworks. For the best experience, make sure to use the view integration layer for your frontend framework of choice.
Apollo Client can be used in any JavaScript frontend where you want to use data from a GraphQL server. It's:
Get started on the home page, which has great examples for a variety of frameworks.
# installing the preset package
npm install apollo-boost graphql-tag graphql --save
# installing each piece independently
npm install apollo-client apollo-cache-inmemory apollo-link-http graphql-tag graphql --save
To use this client in a web browser or mobile app, you'll need a build system capable of loading NPM packages on the client. Some common choices include Browserify, Webpack, and Meteor 1.3+.
Install the Apollo Client Developer tools for Chrome for a great GraphQL developer experience!
You get started by constructing an instance of the core class ApolloClient. If you load ApolloClient from the apollo-boost package, it will be configured with a few reasonable defaults such as our standard in-memory cache and a link to a GraphQL API at /graphql.
import ApolloClient from 'apollo-boost';
const client = new ApolloClient();
To point ApolloClient at a different URL, add your GraphQL API's URL to the uri config property:
import ApolloClient from 'apollo-boost';
const client = new ApolloClient({
uri: 'https://graphql.example.com'
});
Most of the time you'll hook up your client to a frontend integration. But if you'd like to directly execute a query with your client, you may now call the client.query method like this:
import gql from 'graphql-tag';
client.query({
query: gql`
query TodoApp {
todos {
id
text
completed
}
}
`,
})
.then(data => console.log(data))
.catch(error => console.error(error));
Now your client will be primed with some data in its cache. You can continue to make queries, or you can get your client instance to perform all sorts of advanced tasks on your GraphQL data. Such as reactively watching queries with watchQuery, changing data on your server with mutate, or reading a fragment from your local cache with readFragment.
To learn more about all of the features available to you through the apollo-client package, be sure to read through the apollo-client API reference.
Read the Apollo Contributor Guidelines.
Running tests locally:
npm install
npm test
This project uses TypeScript for static typing and TSLint for linting. You can get both of these built into your editor with no configuration by opening this project in Visual Studio Code, an open source IDE which is available for free on all platforms.
If you're getting booted up as a contributor, here are some discussions you should take a look at: