Apollo Client

repository·main·Indexed 12 days ago

https://github.com/apollographql/apollo-client

A fully-featured caching GraphQL client for TypeScript, JavaScript, and frameworks like React, Vue, and Angular. Version 4.2.11 provides intelligent caching, type safety, and advanced developer tools to manage data fetching and state in GraphQL-powered applications.

Tokens
214.7K
Snippets
639
Records
823
Agent score
97%

What's inside Apollo Client

  1. What is Apollo Client?

    main

    Apollo Client is a comprehensive GraphQL state management library for JavaScript. It allows you to manage both local and remote data using GraphQL, enabling you to fetch, cache, and modify application data while automatically updating your UI.

    Key capabilities include:

    • Declarative data fetching: Fetch data via queries without manually managing loading states.
    • Normalized caching: Uses a request and response cache to boost performance by serving cached data immediately.
    • Modern React support: Built to leverage React features like Hooks and Suspense.
    • Incremental adoption: Can be added to existing JavaScript or TypeScript applications feature by feature.
    • Universal compatibility: Works with any build setup and any GraphQL API.
  2. What's new in Apollo Client 4.0

    main

    Apollo Client 4.0 introduces several architectural and developer experience improvements:

    Framework & Bundle Improvements

    • Framework-agnostic core: React-specific exports have moved to @apollo/client/react.
    • ESM Support: Improved support via the exports field in package.json.
    • Observable Implementation: Now uses rxjs instead of zen-observable.
    • Reduced Bundle Size: More features are now opt-in.

    Enhanced Developer Experience

    • TypeScript: Includes stricter variable requirements, more precise return types, namespaced types, and customizable core types.
    • Error Handling: Features a unified error property, granular error classes, and consistent errorPolicy behavior.
  3. What is a terminating link?

    main

    A terminating link is the final link in a link chain. Unlike non-terminating links, it does not call the forward function. Instead, it is responsible for sending the GraphQL operation to its destination (typically a GraphQL server via HTTP) and returning the result.

    Examples of terminating links include HttpLink and BatchHttpLink. If a link chain contains only one link, that link is the terminating link.

  4. What is UnconventionalError and when to use it

    main

    UnconventionalError is a wrapper class used by Apollo Client to normalize non-standard error types. It is encountered when a custom ApolloLink (either your own or from a third-party library) throws something that is not a standard JavaScript Error object, such as a Symbol, an Array, or a plain object.

    Apollo Client does not throw these types itself. You will typically only see this error if you are integrating third-party packages that do not follow standard error-throwing conventions. The purpose of this class is to ensure that Apollo Client's error handling remains consistent while still preserving the original, non-standard error information.

  5. Deciding which arguments belong in `keyArgs`

    main

    Choosing the right keyArgs configuration is a balance between cache hit rate and data integrity:

    • Add to keyArgs if: The argument identifies a logically independent set of data (e.g., category in a feed). Using keyArgs is more declarative and simpler than manually managing data in read and merge functions.
    • Exclude from keyArgs if: The argument limits, filters, sorts, or reprocesses existing data (e.g., offset, limit, filter, sort). Including these in keyArgs creates too many unique storage keys, reducing the cache hit rate and preventing you from retrieving different views of the same data set.
  6. Merge non-normalized objects using `merge: true`

    main

    When a type lacks unique identifier fields (like id), Apollo Client cannot normalize it and instead nests it within its parent. If multiple queries return different fields for the same non-normalized object, Apollo Client will overwrite the object, causing data loss.

    You can prevent this by setting merge: true in the field policy. This tells the cache to use the mergeObjects helper to combine the existing and incoming objects.

    Requirements for merge: true to work:

    1. The objects must occupy the exact same field of the exact same normalized parent.
    2. The objects must have the same __typename.

    Alternatively, you can define merge: true at the type level to apply this behavior to all fields returning that type.

    // Field-level shorthand
    const cache = new InMemoryCache({
      typePolicies: {
        Book: {
          fields: {
            author: {
              merge: true,
            },
          },
        },
      },
    });
    
    // Type-level default (applies to all fields returning Author)
    const cache = new InMemoryCache({
      typePolicies: {
        Author: {
          merge: true,
        },
      },
    });
  7. Best practices for Apollo Client caching

    main

    Optimize your InMemoryCache using these strategies:

    • Identifier Configuration: Use keyFields for types that do not have a standard id field. If a type is meant to group related fields under a parent without a unique identifier, set keyFields: false to disable normalization for that type.
    • Type Policies: Use typePolicies to manage complex logic like pagination or computed fields.
    • Fetch Policies: Use fetchPolicy to control cache behavior per query. Common patterns include cache-first for read-heavy data and network-only for real-time data.
  8. Manage development mode in Apollo Client 4

    main

    In Apollo Client 4, development mode is primarily controlled via the development export condition in package.json.

    • Modern Bundlers: Most modern bundlers will automatically select the correct development or production version based on your build environment.
    • Fallback Behavior: If your build tooling does not support the development or production export conditions, you can still disable development mode by setting the global __DEV__ variable to false.
  9. Strategies for reading and writing cache data

    main

    Apollo Client allows you to interact with cached data (both remote and local) without communicating with your GraphQL server. There are four primary strategies for cache interaction:

    StrategyAPIDescription
    Using GraphQL queriesreadQuery, writeQuery, updateQueryUse standard GraphQL queries to manage remote and local data.
    Using GraphQL fragmentsreadFragment, writeFragment, updateFragment, useFragmentAccess fields of any cached object without needing a full query.
    Directly modifying fieldscache.modifyManipulate cached data without using GraphQL syntax.
    Batching operationscache.batchGroup multiple operations into a single transaction for performance.

    Important Note on References: Avoid updating an object by trying to replace a reference with a new object containing the same reference plus new fields (e.g., changing {__ref: '5'} to {__ref: '5', completed: true}). Instead, use the appropriate update methods to modify the fields of the object the reference points to.

  10. Best practices for GraphQL queries and fragments

    main

    To optimize performance and maintainability in Apollo Client 4.x:

    • Colocation: Each page should ideally have one main query, composed of fragments. Use useFragment or useSuspenseFragment in child components to declare their specific data needs.
    • Fragments for Colocation, not Reuse: Fragments should describe the data needs of a specific component rather than being shared across multiple components for common fields.
    • Incremental Delivery: Use the @defer directive to allow slow fields to stream in later, preventing them from blocking the initial page load.
    • Data Masking: Enable data masking to prevent components from accessing fragment data they do not own, which enforces strict data boundaries.
  11. Choosing between `createSchemaFetch` and MSW for testing

    main

    When performing schema-driven testing, you have two primary choices for intercepting requests:

    1. MSW (Mock Service Worker):

      • Recommended wherever possible.
      • Intercepts requests after they have been dispatched by the application, providing more realistic testing.
      • Supports both REST and GraphQL, making it ideal for applications using a mix of both.
      • Note: If using MSW, you will typically use testSchema.add because MSW usually requires a single, consistent schema setup across tests.
    2. createSchemaFetch:

      • A more lightweight solution.
      • Best used when you want to use testSchema.fork to create a fresh, isolated schema for every single test case.
  12. How query tracking and active/inactive states work in v4

    main

    Apollo Client 4 changed how ObservableQuery instances are tracked to prevent memory leaks. Queries are now only tracked by the client when they are actually subscribed to.

    • Active Query: Observed by at least one subscriber and not in standby.
    • Inactive Query: Observed by at least one subscriber and in standby.
    • Untracked: Any ObservableQuery without at least one subscriber is not tracked or accessible via the client.

    A query is in standby if it is skipped via the skip option or skipToken in a React hook, or if the fetchPolicy is set to standby.

    This change affects client.getObservableQueries and client.refetchQueries (using "active" or "all" keywords), as they no longer include unsubscribed queries.