Docs
Launch GraphOS Studio
You're viewing documentation for a previous version of this software. Switch to the latest stable version.

@apollo/react-hoc

API reference


Installation

npm install @apollo/react-hoc

graphql(query, [config])(component)

import { graphql } from '@apollo/react-hoc';

The graphql() function is the most important thing exported by the @apollo/react-hoc package. With this function you can create higher-order components that can execute queries and update reactively based on the data in your Apollo store. The graphql() function returns a function which will “enhance” any component with reactive capabilities. This follows the React

pattern which is also used by
react-redux’s connect
function.

The graphql() function may be used like this:

function TodoApp({ data: { todos } }) {
return (
<ul>
{todos.map(({ id, text }) => (
<li key={id}>{text}</li>
))}
</ul>
);
}
export default graphql(gql`
query TodoAppQuery {
todos {
id
text
}
}
`)(TodoApp);

You may also define an intermediate function and hook up your component with the graphql() function like this:

// Create our enhancer function.
const withTodoAppQuery = graphql(gql`query { ... }`);
// Enhance our component.
const TodoAppWithData = withTodoAppQuery(TodoApp);
// Export the enhanced component.
export default TodoAppWithData;

The graphql() function will only be able to provide access to your data if there is a

component higher up in your tree to provide an
ApolloClient
instance that will be used to fetch your data.

The behavior of your component enhanced with the graphql() function will be different depending on if your is a

, a
mutation
, or a
subscription
. Go to the appropriate API documentation for more information about the functionality and available options for each type.

Before we look into the specific behaviors of each , let us look at the config object. The config object is the second you pass into the graphql() function, after your . The config is optional and allows you to add some custom behavior to your higher order component.

export default graphql(
gql`{ ... }`,
config, // <- The `config` object.
)(MyComponent);

Lets go through all of the properties that may live on your config object.

config.options

config.options is an object or a function that allows you to define the specific behavior your component should use in handling your data.

The specific options available for configuration depend on the you pass as the first to graphql(). There are options specific to [queries]..(/data/queries/) and

.

You can define config.options as a plain object, or you can compute your options from a function that takes the component’s props as an .

Example:

export default graphql(gql`{ ... }`, {
options: {
// Options go here.
},
})(MyComponent);
export default graphql(gql`{ ... }`, {
options: props => ({
// Options are computed from `props` here.
}),
})(MyComponent);

config.props

The config.props property allows you to define a map function that takes the props (and optionally lastProps) added by the graphql() function (

for queries and
props.mutate
for ) and allows you to compute a new props (and optionally lastProps) object that will be provided to the component that graphql() is wrapping.

The function you define behaves almost exactly like

providing the same benefits without the need for another library.

config.props is most useful when you want to abstract away complex functions calls into a simple prop that you can pass down to your component.

Another benefit of config.props is that it also allows you to decouple your pure UI components from your and Apollo concerns. You can write your pure UI components in one file and then keep the logic required for them to interact with the store in a completely different place in your project. You can accomplish this by your pure UI components only asking for the props needed to render and config.props can contain the logic to provide exactly the props your pure component needs from the data provided by your API.

Example:

This example uses

.

export default graphql(gql`{ ... }`, {
props: ({ data: { fetchMore } }) => ({
onLoadMore: () => {
fetchMore({ ... });
},
}),
})(MyComponent);
function MyComponent({ onLoadMore }) {
return (
<button onClick={onLoadMore}>
Load More!
</button>
);
}

To access props that are not added by the graphql() function, use the ownProps keyword. For example:

export default graphql(gql`{ ... }`, {
props: ({ data: { liveImage }, ownProps: { loadingImage } }) => ({
image: liveImage || loadingImage,
}),
})(MyComponent);

To access lastProps, use the second of config.props. For example:

export default graphql(gql`{ ... }`, {
props: ({ data: { liveImage } }, lastProps) => ({
image: liveImage,
lastImage: lastProps.data.liveImage,
}),
})(MyComponent);

config.skip

If config.skip is true then all of the React Apollo code will be skipped entirely. It will be as if the graphql() function were a simple id function. Your component will behave as if the graphql() function were not there at all.

Instead of passing a boolean to config.skip, you may also pass a function to config.skip. The function will take your components props and should return a boolean. If the boolean returns true then the skip behavior will go into effect.

config.skip is especially useful if you want to use a different based on some prop. You can see this in an example below.

Example:

export default graphql(gql`{ ... }`, {
skip: props => !!props.skip,
})(MyComponent);

The following example uses the

function to use multiple graphql() enhancers at once.

export default compose(
graphql(gql`query MyQuery1 { ... }`, { skip: props => !props.useQuery1 }),
graphql(gql`query MyQuery2 { ... }`, { skip: props => props.useQuery1 }),
)(MyComponent);
function MyComponent({ data }) {
// The data may be from `MyQuery1` or `MyQuery2` depending on the value
// of the prop `useQuery1`.
console.log(data);
}

config.name

This property allows you to configure the name of the prop that gets passed down to your component. By default if the you pass into graphql() is a then your prop will be named

. If you pass a then your prop will be named
mutate
. While appropriate these default names collide when you are trying to use multiple queries or with the same component. To avoid collisions you may use config.name to provide the prop from each or HOC a new name.

Example:

This example uses the

function to use multiple graphql() HOCs together.

export default compose(
graphql(gql`mutation (...) { ... }`, { name: 'createTodo' }),
graphql(gql`mutation (...) { ... }`, { name: 'updateTodo' }),
graphql(gql`mutation (...) { ... }`, { name: 'deleteTodo' }),
)(MyComponent);
function MyComponent(props) {
// Instead of the default prop name, `mutate`,
// we have three different prop names.
console.log(props.createTodo);
console.log(props.updateTodo);
console.log(props.deleteTodo);
return null;
}

config.withRef

By setting config.withRef to true you will be able to get the instance of your wrapped component from your higher-order component using a getWrappedInstance method available on the instance of your higher-order component.

You may want to set this to true when you want to call functions or get access to properties that are defined on your wrapped component’s class instance.

Below you can see an example of this behavior.

Example:

This example uses the

.

class MyComponent extends Component {
saySomething() {
console.log('Hello, world!');
}
render() {
// ...
}
}
const MyGraphQLComponent = graphql(gql`{ ... }`, { withRef: true })(
MyComponent,
);
class MyContainerComponent extends Component {
render() {
return (
<MyGraphQLComponent
ref={component => {
const wrappedInstance = component.getWrappedInstance();
assert(wrappedInstance instanceof MyComponent);
// We can call methods on the component class instance.
wrappedInstance.saySomething();
}}
/>
);
}
}

config.alias

By default the display name for React Apollo components is Apollo(${WrappedComponent.displayName}). This is a pattern used by most React libraries that make use of higher order components. However, it may get a little confusing when you are using more than one higher order component and you look at the

.

To configure the name of your higher order component wrapper, you may use the config.alias property. So for example, if you set config.alias to 'withCurrentUser' your wrapper component display name would be withCurrentUser(${WrappedComponent.displayName}) instead of Apollo(${WrappedComponent.displayName}).

Example:

This example uses the

function to use multiple graphql() HOCs together.

export default compose(
graphql(gql`{ ... }`, { alias: 'withCurrentUser' }),
graphql(gql`{ ... }`, { alias: 'withList' }),
)(MyComponent);

graphql() options for queries

props.data

The higher-order component created when using graphql() will feed a data prop into your component. Like so:

render() {
const { data } = this.props; // <- The `data` prop.
}

The data prop contains the data fetched from your in addition to some other useful information and functions to control the lifecycle of your -connected component. So for example, if we had a query that looked like:

{
viewer {
name
}
todos {
text
}
}

Your data prop would contain that data:

render() {
const { data } = this.props;
console.log(data.viewer); // <- The data returned by your query for `viewer`.
console.log(data.todos); // <- The data returned by your query for `todos`.
}

The data prop has some other useful properties which can be accessed directly from data. For example, data.loading or data.error. These properties are documented below.

Make sure to always check data.loading and data.error in your components before rendering. Properties like data.todos which contain your app’s data may be undefined while your component is performing its initial fetch. Checking data.loading and data.error helps you avoid any issues with undefined data. Such checks may look like:

render() {
const { data: { loading, error, todos } } = this.props;
if (loading) {
return <p>Loading...</p>;
}
if (error) {
return <p>Error!</p>;
}
return (
<ul>
{todos.map(({ id, text }) => (
<li key={id}>{text}</li>
))}
</ul>
);
}

data.loading

A boolean representing whether or not a request is currently in flight for this component. This means that a query request has been sent using your network interface, and we have not yet gotten a response back. Use this property to render a loading component.

However, just because data.loading is true it does not mean that you won’t have data. For instance, if you already have data.todos, but you want to get the latest todos from your API data.loading might be true, but you will still have the todos from your previous request.

There are multiple different network states that your may be in. If you want to see what the network state of your component is in more detail then refer to

.

Example:

function MyComponent({ data: { loading } }) {
if (loading) {
return <div>Loading...</div>;
} else {
// ...
}
}
export default graphql(gql`query { ... }`)(MyComponent);

data.error

If an error occurred then this property will be an instance of ApolloError. If you do not handle this error you will get a warning in your console that says something like: "Unhandled (in react-apollo) Error: ...".

Example:

function MyComponent({ data: { error } }) {
if (error) {
return <div>Error!</div>;
} else {
// ...
}
}
export default graphql(gql`query { ... }`)(MyComponent);

data.networkStatus

data.networkStatus is useful if you want to display a different loading indicator (or no indicator at all) depending on your network status as it provides a more detailed view into the state of a network request on your component than

does. data.networkStatus is an enum with different number values between 1 and 8. These number values each represent a different network state.

  1. loading: The has never been run before and the request is now pending. A query will still have this network status even if a result was returned from the cache, but a query was dispatched anyway.
  2. setVariables: If a ’s change and a network request was fired then the network status will be setVariables until the result of that comes back. React users will see this when
    options.variables
    changes on their queries.
  3. fetchMore: Indicates that fetchMore was called on this and that the network request created is currently in flight.
  4. refetch: It means that refetch was called on a and the refetch request is currently in flight.
  5. Unused.
  6. poll: Indicates that a polling is currently in flight. So for example if you are polling a query every 10 seconds then the network status will switch to poll every 10 seconds whenever a poll request has been sent but not resolved.
  7. ready: No request is in flight for this , and no errors happened. Everything is OK.
  8. error: No request is in flight for this , but one or more errors were detected.

If the network status is less then 7 then it is equivalent to

being true. In fact you could replace all of your data.loading checks with data.networkStatus < 7 and you would not see a difference. It is recommended that you use data.loading, however.

Example:

function MyComponent({ data: { networkStatus } }) {
if (networkStatus === 6) {
return <div>Polling!</div>;
} else if (networkStatus < 7) {
return <div>Loading...</div>;
} else {
// ...
}
}
export default graphql(gql`query { ... }`)(MyComponent);

data.variables

The that Apollo used to fetch data from your endpoint. This property is helpful if you want to render some information based on the variables that were used to make a request against your server.

Example:

function MyComponent({ data: { variables } }) {
return (
<div>
Query executed with the following variables:
<code>{JSON.stringify(variables)}</code>
</div>
);
}
export default graphql(gql`query { ... }`)(MyComponent);

data.refetch(variables)

Forces your component to refetch the you defined in the graphql() function. This method is helpful when you want to reload the data in your component, or retry a fetch after an error.

data.refetch returns a promise that resolves with the new data fetched from your API once the has finished executing. The promise will reject if the query failed.

The data.refetch function takes a single variables object . The variables will replace variables used with either the query option or the from your graphql() HOC (depending on whether or not you specified a query) option to refetch the you defined in the graphql() function.

Example:

function MyComponent({ data: { refetch } }) {
return <button onClick={() => refetch()}>Reload</button>;
}
export default graphql(gql`query { ... }`)(MyComponent);

data.fetchMore(options)

The data.fetchMore function allows you to do pagination with your component. To learn more about pagination with data.fetchMore, be sure to read the

recipe which contains helpful illustrations on how you can do pagination with React Apollo.

data.fetchMore returns a promise that resolves once the executed to fetch more data has resolved.

The data.fetchMore function takes a single options object . The options may take the following properties:

  • [query]: This is an optional created with the gql tag. If you specify a query then that will be fetched when you call data.fetchMore. If you do not specify a query, then the from your graphql() HOC will be used.
  • [variables]: The optional you may provide that will be used with either the query option or the from your graphql() HOC (depending on whether or not you specified a query).
  • updateQuery(previousResult, { fetchMoreResult, variables }): This is the required function you define that will actually update your paginated list. The first , previousResult, will be the previous data returned by the you defined in your graphql() function. The second is an object with two properties, fetchMoreResult and variables. fetchMoreResult is the data returned by the new fetch that used the query and variables options from data.fetchMore. variables are the that were used when fetching more data. Using these you should return a new data object with the same shape as the you defined in your graphql() function. See an example of this below, and also make sure to read the [pagination]..(/data/pagination/) recipe which has a full example.

Example:

data.fetchMore({
updateQuery: (previousResult, { fetchMoreResult, variables }) => {
return {
...previousResult,
// Add the new feed data to the end of the old feed data.
feed: [...previousResult.feed, ...fetchMoreResult.feed],
};
},
});

data.subscribeToMore(options)

This function will set up a , triggering updates whenever the server sends a subscription publication. This requires subscriptions to be set up on the server to properly work. Check out the

and the
subscriptions-transport-ws
and
graphql-subscriptions
for more information on getting this set up.

This function returns an unsubscribe function handler which can be used to unsubscribe later.

A common practice is to wrap the subscribeToMore call within getDerivedStateFromProps and perform the after the original has completed. To ensure the subscription isn't created multiple times, you can add it to component state. See the example for more details.

  • [document]: is a required property that accepts a created with graphql-tag’s gql template string tag. It should contain a single with the data that will be returned.
  • [variables]: The optional you may provide that will be used with the document option.
  • [updateQuery]: An optional function that runs every time the server sends an update. This modifies the results of the HOC . The first , previousResult, will be the previous data returned by the you defined in your graphql() function. The second is an object with two properties. subscriptionData is result of the . variables is the object used with the . Using these you should return a new data object with the same shape as the query you defined in your graphql() function. This is similar to the
    fetchMore
    callback.
  • [onError]: An optional error callback.

In order to update the 's store with the result of the , you must specify either the updateQuery option in subscribeToMore or the reducer option in your graphql() function.

Example:

class SubscriptionComponent extends Component {
state = {
subscriptionParam: null,
unsubscribe: null,
};
static getDerivedStateFromProps(nextProps, prevState) {
if (!nextProps.data.loading) {
// Check for existing subscription
if (prevState.unsubscribe) {
// Only unsubscribe/update state if subscription variable has changed
if (prevState.subscriptionParam === nextProps.subscriptionParam) {
return null;
}
prevState.unsubscribe();
}
return {
// Subscribe
unsubscribe: nextProps.data.subscribeToMore({
document: gql`subscription {...}`,
variables: {
param: nextProps.subscriptionParam,
},
updateQuery: (previousResult, { subscriptionData, variables }) => {
// Perform updates on previousResult with subscriptionData
return updatedResult;
},
}),
// Store subscriptionParam in state for next update
subscriptionParam: nextProps.subscriptionParam,
};
}
return null;
}
render() {
...
}
}

data.startPolling(interval)

This function will set up an interval and send a fetch request every time that interval ellapses. The function takes only one integer which allows you to configure how often you want your to be executed in milliseconds. In other words, the interval represents the milliseconds between polls.

Polling is a good way to keep the data in your UI fresh. By refetching your data every 5,000 milliseconds (or 5 seconds, for example) you may effectively emulate realtime data without needing to build up a realtime backend.

If you call data.startPolling when your is already polling then the current polling process will be cancelled and a new process will be started with the interval you specified.

You may also use

to start polling immediately after your component mounts. It is recommend that you use options.pollInterval if you don’t need to arbitrarily start and stop polling.

If you set your interval to 0 then that means no polling instead of executing a request every JavaScript event loop tick.

Example:

class MyComponent extends Component {
componentDidMount() {
// In this specific case you may want to use `options.pollInterval` instead.
this.props.data.startPolling(1000);
}
render() {
// ...
}
}
export default graphql(gql`query { ... }`)(MyComponent);

data.stopPolling()

By calling this function you will stop any current polling process. Your will not start polling again until you call data.startPolling.

Example:

class MyComponent extends Component {
render() {
return (
<div>
<button
onClick={() => {
this.props.data.startPolling(1000);
}}
>
Start Polling
</button>
<button
onClick={() => {
this.props.data.stopPolling();
}}
>
Stop Polling
</button>
</div>
);
}
}
export default graphql(gql`query { ... }`)(MyComponent);

data.updateQuery(updaterFn)

This function allows you to update the data for your outside of the context of any , , or fetch. This function only takes a single which will be another function. The argument function has the following signature:

(previousResult, { variables }) => nextResult

The first will be the data for your that currently exists in the store, and you are expected to return a new data object with the same shape. That new data object will be written to the store and any components tracking that data will be updated reactively.

The second is an object with a single property, variables. The variables property allows you to see what were used when reading the previousResult from the store.

This method will not update anything on the server. It will only update data in your client cache and if you reload your JavaScript environment then your update will disappear.

Example:

data.updateQuery(previousResult => ({
...previousResult,
count: previousResult.count + 1,
}));

config.options

An object or function that returns an object of options that are used to configure how the is fetched and updated.

If config.options is a function then it will take the component’s props as its first .

The options available for use in this object depend on the type you pass in as the first to graphql(). The references below will document which options are available when your is a . To see what other options are available for different operations, see the generic documentation for

.

Example:

export default graphql(gql`{ ... }`, {
options: {
// Options go here.
},
})(MyComponent);
export default graphql(gql`{ ... }`, {
options: props => ({
// Options are computed from `props` here.
}),
})(MyComponent);

options.variables

The that will be used when executing the . These variables should correspond with the variables that your query definition accepts. If you define config.options as a function then you may compute your from your props.

Example:

export default graphql(
gql`
query ($width: Int!, $height: Int!) {
...
}
`,
{
options: props => ({
variables: {
width: props.size,
height: props.size,
},
}),
},
)(MyComponent);

options.fetchPolicy

The fetch policy is an option which allows you to specify how you want your component to interact with the Apollo data cache. By default your component will try to read from the cache first, and if the full data for your is in the cache then Apollo simply returns the data from the cache. If the full data for your query is not in the cache then Apollo will execute your request using your network interface. By changing this option you can change this behavior.

Valid fetchPolicy values are:

  • cache-first: This is the default value where we always try reading data from your cache first. If all the data needed to fulfill your is in the cache then that data will be returned. Apollo will only fetch from the network if a cached result is not available. This fetch policy aims to minimize the number of network requests sent when rendering your component.
  • cache-and-network: This fetch policy will have Apollo first trying to read data from your cache. If all the data needed to fulfill your is in the cache then that data will be returned. However, regardless of whether or not the full data is in your cache this fetchPolicy will always execute with the network interface unlike cache-first which will only execute your if the query data is not in your cache. This fetch policy optimizes for users getting a quick response while also trying to keep cached data consistent with your server data at the cost of extra network requests.
  • network-only: This fetch policy will never return you initial data from the cache. Instead it will always make a request using your network interface to the server. This fetch policy optimizes for data consistency with the server, but at the cost of an instant response to the user when one is available.
  • cache-only: This fetch policy will never execute a using your network interface. Instead it will always try reading from the cache. If the data for your query does not exist in the cache then an error will be thrown. This fetch policy allows you to only interact with data in your local client cache without making any network requests which keeps your component fast, but means your local data might not be consistent with what is on the server. If you are interested in only interacting with data in your cache also be sure to look at the
    readQuery() and readFragment()
    methods available to you on your ApolloClient instance.
  • no-cache: This fetch policy will never return your initial data from the cache. Instead it will always make a request using your network interface to the server. Unlike the network-only policy, it also will not write any data to the cache after the completes.

Example:

export default graphql(gql`query { ... }`, {
options: { fetchPolicy: 'cache-and-network' },
})(MyComponent);

options.errorPolicy

The error policy is an option which allows you to specify how you want your component to handle errors that can happen when fetching data from . There are two types of errors that can happen during your request; a runtime error on the client or server which results in no data, or some GraphQL errors which may be delivered alongside actual data. In order to control how your UI interacts with these errors, you can use the error policy to tell Apollo when you want to know about GraphQL Errors or not!

Valid errorPolicy values are:

  • none: This is the default value where we treat errors as runtime errors. Apollo will discard any data that came back with the request and render your component with an error prop.
  • ignore: Much like none, this causes Apollo to ignore any data from your server, but it also won't update your UI aside from setting the loading state back to false.
  • all: Selecting all means you want to be notified any time there are any errors. It will render your component with any data from the request and any errors with their information. It is particularly helpful for server side rendering so your UI always shows something

Example:

export default graphql(gql`query { ... }`, {
options: { errorPolicy: 'all' },
})(MyComponent);

options.pollInterval

The interval in milliseconds at which you want to start polling. Whenever that number of milliseconds elapses your will be executed using the network interface and another execution will be scheduled using the configured number of milliseconds.

This option will start polling your immediately when the component mounts. If you want to start and stop polling dynamically then you may use

and
data.stopPolling
.

If you set options.pollInterval to 0 then that means no polling instead of executing a request every JavaScript event loop tick.

Example:

export default graphql(gql`query { ... }`, {
options: { pollInterval: 5000 },
})(MyComponent);

options.notifyOnNetworkStatusChange

Whether or not updates to the network status or network error should trigger re-rendering of your component.

The default value is false.

Example:

export default graphql(gql`query { ... }`, {
options: { notifyOnNetworkStatusChange: true },
})(MyComponent);

options.context

With the flexiblity and power of

being part of , you may want to send information from your straight to a link in your network chain! This can be used to do things like set headers on HTTP requests from props, control which endpoint you send a to, and so much more depending on what links your app is using. Everything under the context object gets passed directly to your network chain. For more information about using context, check out the
docs on context with links

partialRefetch

If true, perform a refetch if the result is marked as being partial, and the returned data is reset to an empty Object by the QueryManager (due to a cache miss).

The default value is false for backwards-compatibility's sake, but should be changed to true for most use-cases.

Example:

export default graphql(gql`query { ... }`, {
options: { partialRefetch: true },
})(MyComponent);

graphql() options for mutations

props.mutate

The higher order component created when you pass a to graphql() will provide your component with a single prop named mutate. Unlike the data prop which you get when you pass a to graphql(), mutate is a function.

The mutate function will actually execute your using the network interface therefore mutating your data. The mutate function will also then update your cache in ways you define.

To learn more about how work, be sure to check out the

.

The mutate function accepts the same options that

for accepts, so make sure to read through the documentation for that to know what you can pass into the mutate function.

The reason the mutate function accepts the same options is that it will use the options from

by default. When you pass an object into the mutate function you are just overriding what is already in
config.options
.

Example:

function MyComponent({ mutate }) {
return (
<button
onClick={() => {
mutate({
variables: { foo: 42 },
});
}}
>
Mutate
</button>
);
}
export default graphql(gql`mutation { ... }`)(MyComponent);

config.options

An object or function that returns an object of options that are used to configure how the is fetched and updated.

If config.options is a function then it will take the component’s props as its first .

The options available for use in this object depend on the type you pass in as the first to graphql(). The references below will document which options are available when your is a . To see what other options are available for different operations, see the generic documentation for

.

The properties accepted in this options object may also be accepted by the

function. Any options passed into the mutate function will take precedence over the options defined in the config object.

Example:

export default graphql(gql`mutation { ... }`, {
options: {
// Options go here.
},
})(MyComponent);
export default graphql(gql`mutation { ... }`, {
options: props => ({
// Options are computed from `props` here.
}),
})(MyComponent);
function MyComponent({ mutate }) {
return (
<button
onClick={() => {
mutate({
// Options are component from `props` and component state here.
});
}}
>
Mutate
</button>
);
}
export default graphql(gql`mutation { ... }`)(MyComponent);

options.variables

The which will be used to execute the . These variables should correspond to the variables that your mutation definition accepts. If you define config.options as a function, or you pass into the

function then you may compute your from props and component state.

Example:

export default graphql(
gql`
mutation ($foo: String!, $bar: String!) {
...
}
`,
{
options: props => ({
variables: {
foo: props.foo,
bar: props.bar,
},
}),
},
)(MyComponent);

options.optimisticResponse

Often when you mutate data it is fairly easy to predict what the response of the will be before asking your server. The optimistic response option allows you to make your mutations feel faster by simulating the result of your mutation in your UI before the mutation actually finishes.

To learn more about the benefits of optimistic data and how to use it be sure to read the recipe on

.

This optimistic response will be used with

and
options.updateQueries
to apply an update to your cache which will be rolled back before applying the update from the actual response.

Example:

function MyComponent({ newText, mutate }) {
return (
<button
onClick={() => {
mutate({
variables: {
text: newText,
},
// The optimistic response has all of the fields that are included in
// the GraphQL mutation document below.
optimisticResponse: {
createTodo: {
id: -1, // A temporary id. The server decides the real id.
text: newText,
completed: false,
},
},
});
}}
>
Add Todo
</button>
);
}
export default graphql(gql`
mutation($text: String!) {
createTodo(text: $text) {
id
text
completed
}
}
`)(MyComponent);

options.update

This option allows you to update your store based on your ’s result. By default will update all of the overlapping nodes in your store. Anything that shares the same id as returned by the dataIdFromObject you defined will be updated with the new from your results. However, sometimes this alone is not sufficient. Sometimes you may want to update your cache in a way that is dependent on the data currently in your cache. For these updates you may use an options.update function.

options.update takes two . The first is an instance of a DataProxy object which has some methods which will allow you to interact with the data in your store. The second is the response from your - either the optimistic response, or the actual response returned by your server (see the mutation result described in the

section for more details).

In order to change the data in your store call methods on your DataProxy instance like

. This will update your cache and reactively re-render any of your components which are affected data.

To read the data from the store that you are changing, make sure to use methods on your DataProxy like

and
readFragment
.

For more information on updating your cache after a with the options.update function make sure to read the

.

Example:

const query = gql`{ todos { ... } }`;
export default graphql(
gql`
mutation ($text: String!) {
createTodo(text: $text) { ... }
}
`,
{
options: {
update: (proxy, { data: { createTodo } }) => {
const data = proxy.readQuery({ query });
data.todos.push(createTodo);
proxy.writeQuery({ query, data });
},
},
},
)(MyComponent);

options.refetchQueries

Sometimes when you make a you also want to update the data in your queries so that your users may see an up-to-date user interface. There are more fine-grained ways to update the data in your cache which include

, and
options.update
. However, you can update the data in your cache more reliably at the cost of efficiency by using options.refetchQueries.

options.refetchQueries will execute one or more queries using your network interface and will then normalize the results of those queries into your cache. Allowing you to potentially refetch queries you had fetched before, or fetch brand new queries.

options.refetchQueries is either an array of strings or objects, or a function which takes the result of the and returns an array of strings or objects.

If options.refetchQueries is an array of strings then will look for any queries with the same names as the provided strings and will refetch those queries with their current . So for example if you have a component with a query named Comments (the may look like: query Comments { ... }), and you pass an array of strings containing Comments to options.refetchQueries then the Comments will be re-executed and when it resolves the latest data will be reflected in your UI.

If options.refetchQueries is an array of objects then the objects must have two properties:

  • query: is a required property that accepts a query created with graphql-tag’s gql template string tag. It should contain a single that will be executed once the has completed.
  • [variables]: Is an optional object of that is required when query accepts some .

If an array of objects with this shape is specified then will refetch these queries with their .

Example:

export default graphql(gql`mutation { ... }`, {
options: {
refetchQueries: ['CommentList', 'PostList'],
},
})(MyComponent);
import { COMMENT_LIST_QUERY } from '../components/CommentList';
export default graphql(gql`mutation { ... }`, {
options: props => ({
refetchQueries: [
{
query: COMMENT_LIST_QUERY,
},
{
query: gql`
query($id: ID!) {
post(id: $id) {
commentCount
}
}
`,
variables: {
id: props.postID,
},
},
],
}),
})(MyComponent);
export default graphql(gql`mutation { ... }`, {
options: {
refetchQueries: mutationResult => ['CommentList', 'PostList'],
},
})(MyComponent);

Please note that refetched queries are handled asynchronously, and by default are not necessarily completed before the has completed. If you want to make sure refetched queries are completed before the mutation is considered done (or resolved), set

to true.

options.awaitRefetchQueries

Queries refetched using

are handled asynchronously, which means by default they are not necessarily completed before the has completed. Setting options.awaitRefetchQueries to true will make sure refetched queries are completed before the is considered done (or resolved). options.awaitRefetchQueries is false by default.

options.updateQueries

Note: We recommend using

instead of updateQueries. updateQueries will be removed in the next version of Apollo Client

This option allows you to update your store based on your ’s result. By default will update all of the overlapping nodes in your store. Anything that shares the same id as returned by the dataIdFromObject you defined will be updated with the new from your results. However, sometimes this alone is not sufficient. Sometimes you may want to update your cache in a way that is dependent on the data currently in your cache. For these updates you may use an options.updateQueries function.

options.updateQueries takes an object where names are the keys and reducer functions are the values. If you are familiar with Redux, defining your options.updateQueries reducers is very similar to defining your Redux reducers. The object looks something like this:

{
Comments: (previousData, { mutationResult, queryVariables }) => nextData,
}

Make sure that the key of your options.updateQueries object corresponds to an actual that you have made somewhere else in your app. The query name will be the name you put after specifying the query type. So for example in the following :

query Comments {
entry(id: 5) {
comments {
...
}
}
}

The name would be Comments. If you have not executed a with the name of Comments before somewhere in your application, then the reducer function will never be run by Apollo and the key/value pair in options.updateQueries will be ignored.

The first to the function you provide as the value for your object will be the previous data for your . So if your key is Comments then the first will be the last data object that was returned for your Comments , or the current object that is being rendered by any component using the Comments .

The second to your function value will be an object with three properties:

  • mutationResult: The mutationResult property will represent the result of your after hitting the server. If you provided an
    options.optimisticResponse
    then mutationResult may be that object.
  • queryVariables: The last set of that the was executed with. This is helpful because when you specify the query name it will only update the data in the store for your current variable set.
  • queryName: This is the name of the you are updating. It is the same name as the key you provided to options.updateQueries.

The return value of your options.updateQueries functions must have the same shape as your first previousData . However, you must not mutate the previousData object. Instead you must create a new object with your changes. Just like in a Redux reducer.

Example:

export default graphql(
gql`
mutation ($text: String!) {
submitComment(text: $text) { ... }
}
`,
{
options: {
updateQueries: {
Comments: (previousData, { mutationResult }) => {
const newComment = mutationResult.data.submitComment;
// Note how we return a new copy of `previousData` instead of mutating
// it. This is just like a Redux reducer!
return {
...previousData,
entry: {
...previousData.entry,
comments: [newComment, ...previousData.entry.comments],
},
};
},
},
},
},
)(MyComponent);

withApollo(component)

import { withApollo } from '@apollo/react-hoc';

A simple enhancer which provides direct access to your

instance. This is useful if you want to do custom logic with Apollo. Such as calling one-off queries. By calling this function with the component you want to enhance, withApollo() will create a new component which passes in an instance of ApolloClient as a client prop.

If you are wondering when to use withApollo() and when to use

the answer is that most of the time you will want to use graphql(). graphql() provides many of the advanced features you need to work with your data. You should only use withApollo() if you want the without any of the other features.

This will only be able to provide access to your client if there is an

component higher up in your tree to actually provide the client.

Example:

function MyComponent({ client }) {
console.log(client);
}
export default withApollo(MyComponent);

ApolloProvider

The ApolloProvider component leverages

to make a configured instance available throughout a React component tree. This component can be imported directly from the @apollo/react-common package where it lives, or from one of the @apollo/react-hooks, @apollo/react-components, and @apollo/react-hoc packages.

import { ApolloProvider } from '@apollo/react-hooks';

Props

OptionTypeDescription
clientApolloClient<TCache>An ApolloClient instance.

Example

ReactDOM.render(
<ApolloProvider client={client}>
<MyRootComponent />
</ApolloProvider>,
document.getElementById('root'),
);
Previous
@apollo/react-components
Next
@apollo/react-common
Edit on GitHubEditForumsDiscord

© 2024 Apollo Graph Inc.

Privacy Policy

Company