<commit_before>---
title: Customizing the behavior of cached fields
sidebar_title: Customizing field behavior
---

You can customize how a particular field in your Apollo Client cache is read and written. To do so, you define a **field policy** for the field. A field policy can include:

* A [`read` function](#the-read-function) that specifies what happens when the field's cached value is read
* A [`merge` function](#the-merge-function) that specifies what happens when field's cached value is written
* An array of [key arguments](#specifying-key-arguments) that help the cache avoid storing unnecessary duplicate data.

You provide field policies to the constructor of `InMemoryCache`. Each field policy is defined inside whatever [`TypePolicy` object](./cache-configuration/#typepolicy-fields)  corresponds to the type that contains the field. The following example defines a field policy for the `name` field of a `Person` type: 

```ts{5-10}
const cache = new InMemoryCache({
  typePolicies: {
    Person: {
      fields: {
        name: {
          read(name) {
            // Return the cached name, transformed to upper case
            return name.toUpperCase();
          }
        }
      },
    },
  },
});
```

The field policy above defines a [`read` function](#the-read-function) that specifies what the cache returns whenever `Person.name` is queried.

## The `read` function

If you define a `read` function for a field, the cache calls that function whenever your client queries for the field. In the query response, the field is populated with the `read` function's return value, _instead of the field's cached value_.

The first parameter of a `read` function provides the field's currently cached value, if one exists. You can use this to help determine the function's return value.

The second parameter is an object that provides access to several properties and helper functions, which are explained in the [`FieldPolicy` API reference](#fieldpolicy-api-reference).

The following `read` function assigns a default value of `UNKNOWN NAME` to the `name` field of a `Person` type, if the actual value is not available in the cache. In all other cases, the cached value is returned.

```ts
const cache = new InMemoryCache({
  typePolicies: {
    Person: {
      fields: {
        name: {
          read(name = "UNKNOWN NAME") {
            return name;
          }
        },
      },
    },
  },
});
```

If a field accepts arguments, the second parameter includes the values of those arguments. The following `read` function checks to see if the `maxLength` argument is provided when the `name` field is queried. If it is, the function returns only the first `maxLength` characters of the person's name. Otherwise, the person's full name is returned.

```ts
const cache = new InMemoryCache({
  typePolicies: {
    Person: {
      fields: {
        // If a field's TypePolicy would only include a read function,
        // you can optionally define the function like so, instead of
        // nesting it inside an object as shown in the example above.
        name(name: string, { args }) {
          if (args && typeof args.maxLength === "number") {
            return name.substring(0, args.maxLength);
          }
          return name;
        },
      },
    },
  },
});
```

You can define a `read` function for a field that isn't even defined in your schema. For example, the following `read` function enables you to query a `userId` field that is always populated with locally stored data:

```ts
const cache = new InMemoryCache({
  typePolicies: {
    Person: {
      fields: {
        userId() {
          return localStorage.loggedInUserId;
        },
      },
    },
  },
});
```

> Note that to query for a field that is only defined locally, your query should [include the `@client` directive](../local-state/managing-state-with-field-policies#querying) on that field so that Apollo Client doesn't include it in requests to your GraphQL server.

Other use cases for a `read` function include:

* Transforming cached data to suit your client's needs, such as rounding floating-point values to the nearest integer
* Deriving local-only fields from one or more schema fields on the same object (such as deriving an `age` field from a `birthDate` field)
* Deriving local-only fields from one or more schema fields across _multiple_ objects

For a full list of the options provided to the `read` function, see the [API reference](#fieldpolicy-api-reference). You will almost never need to use all of these options, but each one has an important role when reading fields from the cache.

## The `merge` function

If you define a `merge` function for a field, the cache calls that function whenever the field is about to be written with an incoming value (such as from your GraphQL server). When the write occurs, the field's new value is set to the `merge` function's return value, _instead of the original incoming value_.

### Merging arrays<commit_msg>Fix localstorage API in cache-field-behavior.md<commit_after>---
title: Customizing the behavior of cached fields
sidebar_title: Customizing field behavior
---

You can customize how a particular field in your Apollo Client cache is read and written. To do so, you define a **field policy** for the field. A field policy can include:

* A [`read` function](#the-read-function) that specifies what happens when the field's cached value is read
* A [`merge` function](#the-merge-function) that specifies what happens when field's cached value is written
* An array of [key arguments](#specifying-key-arguments) that help the cache avoid storing unnecessary duplicate data.

You provide field policies to the constructor of `InMemoryCache`. Each field policy is defined inside whatever [`TypePolicy` object](./cache-configuration/#typepolicy-fields)  corresponds to the type that contains the field. The following example defines a field policy for the `name` field of a `Person` type: 

```ts{5-10}
const cache = new InMemoryCache({
  typePolicies: {
    Person: {
      fields: {
        name: {
          read(name) {
            // Return the cached name, transformed to upper case
            return name.toUpperCase();
          }
        }
      },
    },
  },
});
```

The field policy above defines a [`read` function](#the-read-function) that specifies what the cache returns whenever `Person.name` is queried.

## The `read` function

If you define a `read` function for a field, the cache calls that function whenever your client queries for the field. In the query response, the field is populated with the `read` function's return value, _instead of the field's cached value_.

The first parameter of a `read` function provides the field's currently cached value, if one exists. You can use this to help determine the function's return value.

The second parameter is an object that provides access to several properties and helper functions, which are explained in the [`FieldPolicy` API reference](#fieldpolicy-api-reference).

The following `read` function assigns a default value of `UNKNOWN NAME` to the `name` field of a `Person` type, if the actual value is not available in the cache. In all other cases, the cached value is returned.

```ts
const cache = new InMemoryCache({
  typePolicies: {
    Person: {
      fields: {
        name: {
          read(name = "UNKNOWN NAME") {
            return name;
          }
        },
      },
    },
  },
});
```

If a field accepts arguments, the second parameter includes the values of those arguments. The following `read` function checks to see if the `maxLength` argument is provided when the `name` field is queried. If it is, the function returns only the first `maxLength` characters of the person's name. Otherwise, the person's full name is returned.

```ts
const cache = new InMemoryCache({
  typePolicies: {
    Person: {
      fields: {
        // If a field's TypePolicy would only include a read function,
        // you can optionally define the function like so, instead of
        // nesting it inside an object as shown in the example above.
        name(name: string, { args }) {
          if (args && typeof args.maxLength === "number") {
            return name.substring(0, args.maxLength);
          }
          return name;
        },
      },
    },
  },
});
```

You can define a `read` function for a field that isn't even defined in your schema. For example, the following `read` function enables you to query a `userId` field that is always populated with locally stored data:

```ts
const cache = new InMemoryCache({
  typePolicies: {
    Person: {
      fields: {
        userId() {
          return localStorage.getItem("loggedInUserId");
        },
      },
    },
  },
});
```

> Note that to query for a field that is only defined locally, your query should [include the `@client` directive](../local-state/managing-state-with-field-policies#querying) on that field so that Apollo Client doesn't include it in requests to your GraphQL server.

Other use cases for a `read` function include:

* Transforming cached data to suit your client's needs, such as rounding floating-point values to the nearest integer
* Deriving local-only fields from one or more schema fields on the same object (such as deriving an `age` field from a `birthDate` field)
* Deriving local-only fields from one or more schema fields across _multiple_ objects

For a full list of the options provided to the `read` function, see the [API reference](#fieldpolicy-api-reference). You will almost never need to use all of these options, but each one has an important role when reading fields from the cache.

## The `merge` function

If you define a `merge` function for a field, the cache calls that function whenever the field is about to be written with an incoming value (such as from your GraphQL server). When the write occurs, the field's new value is set to the `merge` function's return value, _instead of the original incoming value_.

### Merging arrays
{'fraction_non_alphanumeric': 0.07991619275665968, 'fraction_numerical': 0.0007981642222887359, 'mean_word_length': 3.3887915936952715, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4031659', 'n_tokens_mistral': 2567, 'n_tokens_neox': 2488, 'n_words': 1321}