From 4d2c68e131b7c4bd6ea4d19263167cc6d293dbc3 Mon Sep 17 00:00:00 2001 From: hwillson Date: Sun, 4 Aug 2019 11:24:19 -0400 Subject: [PATCH 01/25] Why GraphQL Hooks updates --- docs/source/intro/benefits.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/docs/source/intro/benefits.md b/docs/source/intro/benefits.md index 10ccc04..93adb5f 100644 --- a/docs/source/intro/benefits.md +++ b/docs/source/intro/benefits.md @@ -84,19 +84,17 @@ const GET_DOGS = gql` Here, we're describing the shape of the object we want to receive from the server. GraphQL takes care of combining and filtering the data while returning exactly what we ask for. -How do we use this query in our app? Apollo Client builds off of GraphQL's declarative approach to data fetching. In a React app, all of the logic for retrieving your data, tracking loading and error states, and updating your UI is encapsulated in a single `Query` component. This encapsulation makes composing your data fetching components with your presentational components a breeze! Let’s see how to fetch GraphQL data with Apollo Client in a React app: +How do we use this query in our app? Apollo Client builds off of GraphQL's declarative approach to data fetching. In a React app, all of the logic for retrieving your data, tracking loading and error states, and updating your UI is encapsulated in a single `useQuery` Hook. This encapsulation makes composing your data fetching components with your presentational components a breeze! Let’s see how to fetch GraphQL data with Apollo Client in a React app: ```jsx -const Feed = () => ( - - {({ loading, error, data }) => { - if (error) return ; - if (loading || !data) return ; +function Feed() { + const { loading, error, data } = useQuery(GET_DOGS); - return ; - }} - -); + if (error) return ; + if (loading || !data) return ; + + return ; +} ``` Apollo Client takes care of the request cycle from start to finish, including tracking loading and error states for you. There’s no middleware to set up or boilerplate to write before making your first request, nor do you need to worry about transforming and caching the response. All you have to do is describe the data your component needs and let Apollo Client do the heavy lifting. 💪 From cba0b7661700588a3773c3ba32f7dea16bc1a67a Mon Sep 17 00:00:00 2001 From: hwillson Date: Sun, 4 Aug 2019 13:40:32 -0400 Subject: [PATCH 02/25] Connect your API to a client Hooks changes --- docs/source/tutorial/client.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/source/tutorial/client.md b/docs/source/tutorial/client.md index 8debc16..4b46ad3 100644 --- a/docs/source/tutorial/client.md +++ b/docs/source/tutorial/client.md @@ -124,16 +124,16 @@ Go ahead and delete the `client.query()` call you just made and the `gql` import ## Connect your client to React -Connecting Apollo Client to our React app with `react-apollo` allows us to easily bind GraphQL operations to our UI. +Connecting Apollo Client to our React app with React Apollo allows us to easily bind GraphQL operations to our UI. -To connect Apollo Client to React, we will wrap our app in the `ApolloProvider` component exported from the `react-apollo` package and pass our client to the `client` prop. The `ApolloProvider` component is similar to React’s context provider. It wraps your React app and places the client on the context, which allows you to access it from anywhere in your component tree. +To connect Apollo Client to React, we will wrap our app in the `ApolloProvider` component exported from the `@apollo/react-hooks` package and pass our client to the `client` prop. The `ApolloProvider` component is similar to React’s context provider. It wraps your React app and places the client on the context, which allows you to access it from anywhere in your component tree. Open `src/index.js` and add the following lines of code: _src/index.js_ -```jsx{1,4,6} -import { ApolloProvider } from 'react-apollo'; +```jsx +import { ApolloProvider } from '@apollo/react-hooks'; import React from 'react'; import ReactDOM from 'react-dom'; import Pages from './pages'; @@ -147,4 +147,4 @@ ReactDOM.render( ); ``` -Now, we're ready to start building our first `Query` components in the next section. +Now, we're ready to start building our first `useQuery` Hook based component in the next section. From 4c3f5e0b56a83a885f713d9d8d882b04e6e487d4 Mon Sep 17 00:00:00 2001 From: hwillson Date: Sun, 4 Aug 2019 13:56:14 -0400 Subject: [PATCH 03/25] Fetch data with queries Hooks updates --- docs/source/tutorial/queries.md | 145 +++++++++++++++----------------- 1 file changed, 67 insertions(+), 78 deletions(-) diff --git a/docs/source/tutorial/queries.md b/docs/source/tutorial/queries.md index 68aa020..3efd66a 100644 --- a/docs/source/tutorial/queries.md +++ b/docs/source/tutorial/queries.md @@ -1,21 +1,21 @@ --- title: "6. Fetch data with queries" -description: Learn how to fetch data with the Query component +description: Learn how to fetch data with the useQuery Hook --- Time to accomplish: _15 Minutes_ -Apollo Client simplifies fetching data from a graph API because it intelligently caches your data, as well as tracks loading and error state. In the previous section, we learned how to fetch a sample query with Apollo Client without using a view integration. In this section, we'll learn how to use the `Query` component from `react-apollo` to fetch more complex queries and execute features like pagination. +Apollo Client simplifies fetching data from a graph API because it intelligently caches your data, as well as tracks loading and error state. In the previous section, we learned how to fetch a sample query with Apollo Client without using a view integration. In this section, we'll learn how to use the `useQuery` Hook from `@apollo/react-hooks` to fetch more complex queries and execute features like pagination. -## The Query component +## The useQuery Hook -The `Query` component is one of the most important building blocks of an Apollo app. It's a React component that fetches a GraphQL query and exposes the result so you can render your UI based on the data it returns. +The `useQuery` Hook is one of the most important building blocks of an Apollo app. It's a React Hook that fetches a GraphQL query and exposes the result so you can render your UI based on the data it returns. -The `Query` component uses the **render prop** pattern to fetch and load data from queries into our UI. The render prop pattern provides the ability to add a function as a child to our `Query` component that will notify React about what you want to render. It exposes the `error`, `loading` and `data` on a result object that is passed into the render prop function. Let's see an example: +The `useQuery` Hook leverages React's [Hooks API](https://reactjs.org/docs/hooks-intro.html) to fetch and load data from queries into our UI. It exposes `error`, `loading` and `data` properties through a result object, that help us populate and render our component. Let's see an example: ## Fetching a list -To create a `Query` component, import `Query` from `react-apollo`, pass your query wrapped with `gql` to `this.props.query`, and provide a render prop function to `this.props.children` that uses the `loading`, `data`, and `error` properties on the result object to render UI in your app. +To create a component with `useQuery`, import `useQuery` from `@apollo/react-hooks`, pass your query wrapped with `gql` in as the first parameter, then wire your component up to use the `loading`, `data`, and `error` properties on the result object to render UI in your app. First, we're going to build a GraphQL query that fetches a list of launches. We're also going to import some components that we will need in the next step. Navigate to `src/pages/launches.js` to get started and copy the code below into the file. @@ -23,7 +23,7 @@ _src/pages/launches.js_ ```js import React, { Fragment } from 'react'; -import { Query } from 'react-apollo'; +import { useQuery } from '@apollo/react-hooks'; import gql from 'graphql-tag'; import { LaunchTile, Header, Button, Loading } from '../components'; @@ -52,38 +52,33 @@ const GET_LAUNCHES = gql` Here, we're defining a query to fetch a list of launches by calling the `launches` query from our schema. The `launches` query returns an object type with a list of launches, in addition to the `cursor` of the paginated list and whether or not the list `hasMore` launches. We need to wrap the query with the `gql` function in order to parse it into an AST. -Now, let's pass that query to Apollo's `Query` component to render the list: +Now, let's pass that query to Apollo's `useQuery` component to render the list: _src/pages/launches.js_ ```jsx export default function Launches() { - return ( - - {({ data, loading, error }) => { - if (loading) return ; - if (error) return

ERROR

; + const { data, loading, error } = useQuery(GET_LAUNCHES); + if (loading) return ; + if (error) return

ERROR

; - return ( - -
- {data.launches && - data.launches.launches && - data.launches.launches.map(launch => ( - - ))} - - ); - }} - + return ( + +
+ {data.launches && + data.launches.launches && + data.launches.launches.map(launch => ( + + ))} + ); -}; +} ``` -To render the list, we pass the `GET_LAUNCHES` query from the previous step into our `Query` component. We then define a render prop function as the child of `Query` that's called with the state of our query (`loading`, `error`, and `data`). Depending on the state, we either render a loading indicator, an error message, or a list of launches. +To render the list, we pass the `GET_LAUNCHES` query from the previous step into our `useQuery` Hook. Then, depending on the state of `loading`, `error`, and `data`, we either render a loading indicator, an error message, or a list of launches. We're not done yet! Right now, this query is only fetching the first 20 launches from the list. To fetch the full list of launches, we need to build a pagination feature that displays a `Load More` button for loading more items on the screen. Let's learn how! @@ -91,20 +86,17 @@ We're not done yet! Right now, this query is only fetching the first 20 launches Apollo Client has built-in helpers to make adding pagination to our app much easier than it would be if we were writing the logic ourselves. -To build a paginated list with Apollo, we first need to destructure the `fetchMore` function from the `Query` render prop function. +To build a paginated list with Apollo, we first need to destructure the `fetchMore` function from the `useQuery` result object: _src/pages/launches.js_ ```jsx export default function Launches() { + const { data, loading, error, fetchMore } = useQuery(GET_LAUNCHES); // highlight-line return ( - - {({ data, loading, error, fetchMore }) => { // highlight-line - // same as above - }} - + // same as above ); -}; +} ``` Now that we have `fetchMore`, let's connect it to a Load More button to fetch more items when it's clicked. To do this, we will need to specify an `updateQuery` function on the return object from `fetchMore` that tells the Apollo cache how to update our query with the new items we're fetching. @@ -158,7 +150,7 @@ _src/pages/launch.js_ ```jsx import React, { Fragment } from 'react'; -import { Query } from 'react-apollo'; +import { useQuery } from '@apollo/react-hooks'; import gql from 'graphql-tag'; import Loading from '../components/loading'; @@ -186,29 +178,27 @@ export const GET_LAUNCH_DETAILS = gql` `; ``` -Now that we have a query, let's render a `Query` component to execute it. This time, we'll also need to pass in the `launchId` as a variable to the query, which we'll do by adding a `variables` prop to `Query`. The `launchId` comes through as a prop from the router. +Now that we have a query, let's render a component with `useQuery` to execute it. This time, we'll also need to pass in the `launchId` as a variable to the query, which we'll do by adding a `variables` option to `useQuery`. The `launchId` comes through as a prop from the router. _src/pages/launch.js_ ```jsx export default function Launch({ launchId }) { - return ( - - {({ data, loading, error }) => { - if (loading) return ; - if (error) return

ERROR: {error.message}

; + const { data, loading, error } = useQuery( + GET_LAUNCH_DETAILS, + { variables: { launchId } } + ); + if (loading) return ; + if (error) return

ERROR: {error.message}

; - return ( - -
- {data.launch.mission.name} -
- - -
- ); - }} -
+ return ( + +
+ {data.launch.mission.name} +
+ + +
); } ``` @@ -284,7 +274,7 @@ Great, now we've successfully refactored our queries to use fragments. Fragments ### Customizing the fetch policy -Sometimes, it's useful to tell Apollo Client to bypass the cache altogether if you have some data that constantly needs to be refreshed. We can do this by customizing the `Query` component's `fetchPolicy`. +Sometimes, it's useful to tell Apollo Client to bypass the cache altogether if you have some data that constantly needs to be refreshed. We can do this by customizing the `useQuery` Hook's `fetchPolicy`. First, let's navigate to `src/pages/profile.js` and write our query: @@ -292,7 +282,7 @@ _src/pages/profile.js_ ```js import React, { Fragment } from 'react'; -import { Query } from 'react-apollo'; +import { useQuery } from '@apollo/react-hooks'; import gql from 'graphql-tag'; import { Loading, Header, LaunchTile } from '../components'; @@ -312,36 +302,35 @@ const GET_MY_TRIPS = gql` `; ``` -Next, let's render a `Query` component to fetch a logged in user's list of trips. By default, Apollo Client's fetch policy is `cache-first`, which means it checks the cache to see if the result is there before making a network request. Since we want this list to always reflect the newest data from our graph API, we set the `fetchPolicy` for this query to `network-only`: +Next, let's render a component with `useQuery` to fetch a logged in user's list of trips. By default, Apollo Client's fetch policy is `cache-first`, which means it checks the cache to see if the result is there before making a network request. Since we want this list to always reflect the newest data from our graph API, we set the `fetchPolicy` for this query to `network-only`: _src/pages/profile.js_ ```jsx export default function Profile() { - return ( - {/* highlight-line */} - {({ data, loading, error }) => { - if (loading) return ; - if (error) return

ERROR: {error.message}

; + const { data, loading, error } = useQuery( + GET_MY_TRIPS, + { fetchPolicy: "network-only" } // highlight-line + ); - return ( - -
My Trips
- {data.me && data.me.trips.length ? ( - data.me.trips.map(launch => ( - - )) - ) : ( -

You haven't booked any trips

- )} -
- ); - }} -
+ if (loading) return ; + if (error) return

ERROR: {error.message}

; + + return ( + +
My Trips
+ {data.me && data.me.trips.length ? ( + data.me.trips.map(launch => ( + + )) + ) : ( +

You haven't booked any trips

+ )} +
); } ``` If you try to render this query, you'll notice that it returns null. This is because we need to implement our login feature first. We're going to tackle login in the next section. -Now that we've learned how to build `Query` components that can fetch a paginated list, share fragments, and customize the fetch policy, it's time to progress to the next section so we can learn how to update data with mutations! +Now that we've learned how to leverage `useQuery` to build components that can fetch a paginated list, share fragments, and customize the fetch policy, it's time to progress to the next section so we can learn how to update data with mutations! From 6746f5e9888e64249ff24396dc3649638c097e44 Mon Sep 17 00:00:00 2001 From: hwillson Date: Sun, 4 Aug 2019 14:06:19 -0400 Subject: [PATCH 04/25] Update data with mutations Hooks updates --- docs/source/tutorial/mutations.md | 67 +++++++++++++++---------------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/docs/source/tutorial/mutations.md b/docs/source/tutorial/mutations.md index 9b1a7b0..767ae7e 100644 --- a/docs/source/tutorial/mutations.md +++ b/docs/source/tutorial/mutations.md @@ -1,19 +1,19 @@ --- title: '7. Update data with mutations' -description: Learn how to update data with the Mutation component +description: Learn how to update data with the useMutation Hook --- Time to accomplish: _12 Minutes_ -With Apollo Client, updating data from a graph API is as simple as calling a function. Additionally, the Apollo Client cache is smart enough to automatically update in most cases. In this section, we'll learn how to use the `Mutation` component from `react-apollo` to login a user. +With Apollo Client, updating data from a graph API is as simple as calling a function. Additionally, the Apollo Client cache is smart enough to automatically update in most cases. In this section, we'll learn how to use the `useMutation` Hook from React Apollo to login a user. -## What is a Mutation component? +## What is the useMutation Hook? -The `Mutation` component is another important building block in an Apollo app. It's a React component that provides a function to execute a GraphQL mutation. Additionally, it tracks the loading, completion, and error state of that mutation. +The `useMutation` Hook is another important building block in an Apollo app. It leverages React's [Hooks API](https://reactjs.org/docs/hooks-intro.html) to provide a function to execute a GraphQL mutation. Additionally, it tracks the loading, completion, and error state of that mutation. -Updating data with a `Mutation` component from `react-apollo` is very similar to fetching data with a `Query` component. The main difference is that the first argument to the `Mutation` render prop function is a **mutate function** that actually triggers the mutation when it is called. The second argument to the `Mutation` render prop function is a result object that contains loading and error state, as well as the return value from the mutation. Let's see an example: +Updating data with a `useMutation` Hook from `@apollo/react-hooks` is very similar to fetching data with a `useQuery` Hook. The main difference is that the first value in the `useMutation` result tuple is a **mutate function** that actually triggers the mutation when it is called. The second value in the result tuple is a result object that contains loading and error state, as well as the return value from the mutation. Let's see an example: -## Update data with Mutation +## Update data with useMutation The first step is defining our GraphQL mutation. To start, navigate to `src/pages/login.js` and copy the code below so we can start building out the login screen: @@ -21,7 +21,7 @@ _src/pages/login.js_ ```js import React from 'react'; -import { Mutation, ApolloConsumer } from 'react-apollo'; +import { ApolloConsumer, useMutation } from '@apollo/react-hooks'; import gql from 'graphql-tag'; import { LoginForm, Loading } from '../components'; @@ -33,56 +33,53 @@ const LOGIN_USER = gql` `; ``` -Just like before, we're using the `gql` function to wrap our GraphQL mutation so it can be parsed into an AST. We're also importing some components that we'll use in the next steps. Now, let's bind this mutation to our component by passing it to the `mutation` prop: +Just like before, we're using the `gql` function to wrap our GraphQL mutation so it can be parsed into an AST. We're also importing some components that we'll use in the next steps. Now, let's bind this mutation to our component by passing it to the `useMutation` Hook: _src/pages/login.js_ ```jsx export default function Login() { - return ( - - {(login, { data }) => } - - ); + const [login, { data }] = useMutation(LOGIN_USER); + return ; } ``` -Our `Mutation` component takes a render prop function as a child that exposes a mutate function (`login`) and the data object returned from the mutation. Finally, we pass our login function to the `LoginForm` component. +Our `useMutation` Hook returns a mutate function (`login`) and the data object returned from the mutation. Finally, we pass our login function to the `LoginForm` component. -To create a better experience for our users, we want to persist the login between sessions. In order to do that, we need to save our login token to `localStorage`. Let's learn how we can use the `onCompleted` handler on `Mutation` to persist our login: +To create a better experience for our users, we want to persist the login between sessions. In order to do that, we need to save our login token to `localStorage`. Let's learn how we can use the `onCompleted` handler of `useMutation` to persist our login: ### Expose Apollo Client with ApolloConsumer -One of the main functions of `react-apollo` is that it puts your `ApolloClient` instance on React's context. Sometimes, we need to access the `ApolloClient` instance to directly call a method that isn't exposed by the `react-apollo` helper components. The `ApolloConsumer` component can help us access the client. +One of the main functions of React Apollo is that it puts your `ApolloClient` instance on React's context. Sometimes, we need to access the `ApolloClient` instance to directly call a method that isn't exposed by the `@apollo/react-hooks` helper components. The `ApolloConsumer` component can help us access the client. -`ApolloConsumer` takes a render prop function as a child that is called with the client instance. Let's wrap our `Mutation` component with `ApolloConsumer` to expose the client. Next, we want to pass an `onCompleted` callback to `Mutation` that will be called once the mutation is complete with its return value. This callback is where we will save the login token to `localStorage`. +`ApolloConsumer` takes a render prop function as a child that is called with the client instance. Let's wrap our `useMutation` based component with `ApolloConsumer` to expose the client. Next, we want to pass an `onCompleted` callback to `useMutation` that will be called once the mutation is complete with its return value. This callback is where we will save the login token to `localStorage`. In our `onCompleted` handler, we also call `client.writeData` to write local data to the Apollo cache indicating that the user is logged in. This is an example of a **direct write** that we'll explore further in the next section on local state management. _src/pages/login.js_ -```jsx{3,4,7-10,22} +```jsx{5-8,13-14,22} export default function Login() { + const [login, { loading, error }] = useMutation( + LOGIN_USER, + { + onCompleted({ login }) { + localStorage.setItem('token', login); + client.writeData({ data: { isLoggedIn: true } }); + } + } + ); + return ( - {client => ( - { - localStorage.setItem('token', login); - client.writeData({ data: { isLoggedIn: true } }); - }} - > - {(login, { loading, error }) => { - // this loading state will probably never show, but it's helpful to - // have for testing - if (loading) return ; - if (error) return

An error occurred

; + {client => { + // this loading state will probably never show, but it's helpful to + // have for testing + if (loading) return ; + if (error) return

An error occurred

; - return ; - }} -
- )} + return ; + }}
); } From 7be6846f80f96bd7ba765eb29b1c9b3c29f6560b Mon Sep 17 00:00:00 2001 From: hwillson Date: Sun, 4 Aug 2019 14:34:50 -0400 Subject: [PATCH 05/25] Manage local state Hooks updates --- docs/source/tutorial/local-state.md | 156 +++++++++++++--------------- 1 file changed, 74 insertions(+), 82 deletions(-) diff --git a/docs/source/tutorial/local-state.md b/docs/source/tutorial/local-state.md index 218faf9..beb4395 100644 --- a/docs/source/tutorial/local-state.md +++ b/docs/source/tutorial/local-state.md @@ -85,8 +85,8 @@ Let's look at an example where we query the `isLoggedIn` field we wrote to the c _src/index.js_ -```jsx{8,17-19} -import { Query, ApolloProvider } from 'react-apollo'; +```jsx{8-12,15} +import { ApolloProvider, Query } from '@apollo/react-hooks'; import gql from 'graphql-tag'; import Pages from './pages'; @@ -99,18 +99,21 @@ const IS_LOGGED_IN = gql` } `; +function IsLoggedIn() { + const { data } = useQuery(IS_LOGGED_IN); + return data.isLoggedIn ? : ; +} + injectStyles(); ReactDOM.render( - - {({ data }) => (data.isLoggedIn ? : )} - + , document.getElementById('root'), ); ``` -First, we create our `IsUserLoggedIn` local query by adding the `@client` directive to the `isLoggedIn` field. Then, we render a `Query` component, pass our local query in, and specify a render prop function that renders either a login screen or the homepage depending if the user is logged in. Since cache reads are synchronous, we don't have to account for any loading state. +First, we create our `IsUserLoggedIn` local query by adding the `@client` directive to the `isLoggedIn` field. Then, we render a component with `useQuery`, pass our local query in, and based on the response render either a login screen or the homepage depending if the user is logged in. Since cache reads are synchronous, we don't have to account for any loading state. Let's look at another example of a component that queries local state in `src/pages/cart.js`. Just like before, we create our query: @@ -118,7 +121,7 @@ _src/pages/cart.js_ ```js import React, { Fragment } from 'react'; -import { Query } from 'react-apollo'; +import { useQuery } from '@apollo/react-hooks'; import gql from 'graphql-tag'; import { Header, Loading } from '../components'; @@ -131,34 +134,29 @@ export const GET_CART_ITEMS = gql` `; ``` -Next, we render our `Query` component and bind it to our `GetCartItems` query: +Next, we call `useQuery` and bind it to our `GetCartItems` query: _src/pages/cart.js_ ```jsx export default function Cart() { + const { data, loading, error } = useQuery(GET_CART_ITEMS); + if (loading) return ; + if (error) return

ERROR: {error.message}

; return ( - - {({ data, loading, error }) => { - if (loading) return ; - if (error) return

ERROR: {error.message}

; - return ( - -
My Cart
- {!data.cartItems || !data.cartItems.length ? ( -

No items in your cart

- ) : ( - - {data.cartItems.map(launchId => ( - - ))} - - - )} -
- ); - }} -
+ +
My Cart
+ {!data.cartItems || !data.cartItems.length ? ( +

No items in your cart

+ ) : ( + + {data.cartItems.map(launchId => ( + + ))} + + + )} +
); } ``` @@ -226,14 +224,14 @@ Up until now, we've focused on querying local data from the Apollo cache. Apollo ### Direct cache writes -Direct cache writes are convenient when you want to write a simple field, like a boolean or a string, to the Apollo cache. We perform a direct write by calling `client.writeData()` and passing in an object with a data property that corresponds to the data we want to write to the cache. We've already seen an example of a direct write, when we called `client.writeData` in the `onCompleted` handler for the login `Mutation` component. Let's look at a similar example, where we copy the code below to create a logout button: +Direct cache writes are convenient when you want to write a simple field, like a boolean or a string, to the Apollo cache. We perform a direct write by calling `client.writeData()` and passing in an object with a data property that corresponds to the data we want to write to the cache. We've already seen an example of a direct write, when we called `client.writeData` in the `onCompleted` handler for the login `useMutation` based component. Let's look at a similar example, where we copy the code below to create a logout button: _src/containers/logout-button.js_ ```jsx import React from 'react'; import styled from 'react-emotion'; -import { ApolloConsumer } from 'react-apollo'; +import { ApolloConsumer } from '@apollo/react-hooks'; import { menuItemClassName } from '../components/menu-item'; import { ReactComponent as ExitIcon } from '../assets/icons/exit.svg'; @@ -265,13 +263,13 @@ const StyledButton = styled('button')(menuItemClassName, { When we click the button, we perform a direct cache write by calling `client.writeData` and passing in a data object that sets the `isLoggedIn` boolean to false. -We can also perform direct writes within the `update` function of a `Mutation` component. The `update` function allows us to manually update the cache after a mutation occurs without refetching data. Let's look at an example in `src/containers/book-trips.js`: +We can also perform direct writes within the `update` function of the `useMutation` Hook. The `update` function allows us to manually update the cache after a mutation occurs without refetching data. Let's look at an example in `src/containers/book-trips.js`: _src/containers/book-trips.js_ -```jsx{30-32} +```jsx{29-31} import React from 'react'; -import { Mutation } from 'react-apollo'; +import { useMutation } from '@apollo/react-hooks'; import gql from 'graphql-tag'; import Button from '../components/button'; @@ -291,29 +289,25 @@ const BOOK_TRIPS = gql` `; export default function BookTrips({ cartItems }) { - return ( - ({ + const [bookTrips, { data, loading, error }] = useMutation( + BOOK_TRIPS, + { + refetchQueries: cartItems.map(launchId => ({ query: GET_LAUNCH, variables: { launchId }, - }))} - update={cache => { + })), + update(cache) { cache.writeData({ data: { cartItems: [] } }); - }} - > - {(bookTrips, { data, loading, error }) => - data && data.bookTrips && !data.bookTrips.success ? ( -

{data.bookTrips.message}

- ) : ( - - ) } -
- ); + } + ) + return data && data.bookTrips && !data.bookTrips.success + ?

{data.bookTrips.message}

+ : ( + + ); } ``` @@ -368,7 +362,7 @@ _src/containers/action-button.js_ ```jsx import React from 'react'; -import { Mutation } from 'react-apollo'; +import { useMutation } from '@apollo/react-hooks'; import gql from 'graphql-tag'; import { GET_LAUNCH_DETAILS } from '../pages/launch'; @@ -388,43 +382,41 @@ const CANCEL_TRIP = gql` `; export default function ActionButton({ isBooked, id, isInCart }) { - return ( - - {(mutate, { loading, error }) => { - if (loading) return

Loading...

; - if (error) return

An error occurred

; + ] + } + ); - return ( -
- -
- ); - }} -
+ if (loading) return

Loading...

; + if (error) return

An error occurred

; + + return ( +
+ +
); } ``` -In this example, we're using the `isBooked` prop passed into the component to determine which mutation we should fire. Just like remote mutations, we can pass in our local mutations to the same `Mutation` component. +In this example, we're using the `isBooked` prop passed into the component to determine which mutation we should fire. Just like remote mutations, we can pass in our local mutations to the same `useMutation` Hook. --- From b102fc056198b3c51216fab0a7176dec703ba01f Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Mon, 5 Aug 2019 13:15:32 -0400 Subject: [PATCH 06/25] Update docs/source/tutorial/client.md Co-Authored-By: Peggy Rayzis --- docs/source/tutorial/client.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/client.md b/docs/source/tutorial/client.md index 4b46ad3..a913c65 100644 --- a/docs/source/tutorial/client.md +++ b/docs/source/tutorial/client.md @@ -124,7 +124,7 @@ Go ahead and delete the `client.query()` call you just made and the `gql` import ## Connect your client to React -Connecting Apollo Client to our React app with React Apollo allows us to easily bind GraphQL operations to our UI. +Connecting Apollo Client to our React app with Apollo's hooks allows us to easily bind GraphQL operations to our UI. To connect Apollo Client to React, we will wrap our app in the `ApolloProvider` component exported from the `@apollo/react-hooks` package and pass our client to the `client` prop. The `ApolloProvider` component is similar to React’s context provider. It wraps your React app and places the client on the context, which allows you to access it from anywhere in your component tree. From f6b699d35f83a9f4c884091eb09ccd3c7ba29108 Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Mon, 5 Aug 2019 13:15:56 -0400 Subject: [PATCH 07/25] Update docs/source/tutorial/client.md Co-Authored-By: Peggy Rayzis --- docs/source/tutorial/client.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/client.md b/docs/source/tutorial/client.md index a913c65..bf71bf5 100644 --- a/docs/source/tutorial/client.md +++ b/docs/source/tutorial/client.md @@ -147,4 +147,4 @@ ReactDOM.render( ); ``` -Now, we're ready to start building our first `useQuery` Hook based component in the next section. +Now, we're ready to start building our first component with the `useQuery` hook in the next section. From 1d3560a3b008ce3b2a61de5ac6cb97bb3e991b32 Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Mon, 5 Aug 2019 13:16:18 -0400 Subject: [PATCH 08/25] Update docs/source/tutorial/local-state.md Co-Authored-By: Peggy Rayzis --- docs/source/tutorial/local-state.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/local-state.md b/docs/source/tutorial/local-state.md index beb4395..d050192 100644 --- a/docs/source/tutorial/local-state.md +++ b/docs/source/tutorial/local-state.md @@ -263,7 +263,7 @@ const StyledButton = styled('button')(menuItemClassName, { When we click the button, we perform a direct cache write by calling `client.writeData` and passing in a data object that sets the `isLoggedIn` boolean to false. -We can also perform direct writes within the `update` function of the `useMutation` Hook. The `update` function allows us to manually update the cache after a mutation occurs without refetching data. Let's look at an example in `src/containers/book-trips.js`: +We can also perform direct writes within the `update` function of the `useMutation` hook. The `update` function allows us to manually update the cache after a mutation occurs without refetching data. Let's look at an example in `src/containers/book-trips.js`: _src/containers/book-trips.js_ From 6c70969e637124c9b1b080ca476031b90d9513c3 Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Mon, 5 Aug 2019 13:16:38 -0400 Subject: [PATCH 09/25] Update docs/source/tutorial/local-state.md Co-Authored-By: Peggy Rayzis --- docs/source/tutorial/local-state.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/local-state.md b/docs/source/tutorial/local-state.md index d050192..c297ab1 100644 --- a/docs/source/tutorial/local-state.md +++ b/docs/source/tutorial/local-state.md @@ -416,7 +416,7 @@ export default function ActionButton({ isBooked, id, isInCart }) { } ``` -In this example, we're using the `isBooked` prop passed into the component to determine which mutation we should fire. Just like remote mutations, we can pass in our local mutations to the same `useMutation` Hook. +In this example, we're using the `isBooked` prop passed into the component to determine which mutation we should fire. Just like remote mutations, we can pass in our local mutations to the same `useMutation` hook. --- From 7b0d5ed02d2f8f99c0d1e0680cdc6923a8f9a080 Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Mon, 5 Aug 2019 13:16:50 -0400 Subject: [PATCH 10/25] Update docs/source/tutorial/mutations.md Co-Authored-By: Peggy Rayzis --- docs/source/tutorial/mutations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/mutations.md b/docs/source/tutorial/mutations.md index 767ae7e..5dc6fc8 100644 --- a/docs/source/tutorial/mutations.md +++ b/docs/source/tutorial/mutations.md @@ -1,6 +1,6 @@ --- title: '7. Update data with mutations' -description: Learn how to update data with the useMutation Hook +description: Learn how to update data with the useMutation hook --- Time to accomplish: _12 Minutes_ From 6d120691a5f3fdf5dc4bcf4a037c9f277cfe8b51 Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Mon, 5 Aug 2019 13:17:09 -0400 Subject: [PATCH 11/25] Update docs/source/intro/benefits.md Co-Authored-By: Peggy Rayzis --- docs/source/intro/benefits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/intro/benefits.md b/docs/source/intro/benefits.md index 93adb5f..7e6ce0a 100644 --- a/docs/source/intro/benefits.md +++ b/docs/source/intro/benefits.md @@ -84,7 +84,7 @@ const GET_DOGS = gql` Here, we're describing the shape of the object we want to receive from the server. GraphQL takes care of combining and filtering the data while returning exactly what we ask for. -How do we use this query in our app? Apollo Client builds off of GraphQL's declarative approach to data fetching. In a React app, all of the logic for retrieving your data, tracking loading and error states, and updating your UI is encapsulated in a single `useQuery` Hook. This encapsulation makes composing your data fetching components with your presentational components a breeze! Let’s see how to fetch GraphQL data with Apollo Client in a React app: +How do we use this query in our app? Apollo Client builds off of GraphQL's declarative approach to data fetching. In a React app, all of the logic for retrieving your data, tracking loading and error states, and updating your UI is encapsulated in a single `useQuery` hook. This encapsulation makes composing your data fetching components with your presentational components a breeze! Let’s see how to fetch GraphQL data with Apollo Client in a React app: ```jsx function Feed() { From 2ee29d36961d56e1d1c1c1b2f54b5d37b75208b3 Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Mon, 5 Aug 2019 13:17:22 -0400 Subject: [PATCH 12/25] Update docs/source/tutorial/mutations.md Co-Authored-By: Peggy Rayzis --- docs/source/tutorial/mutations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/mutations.md b/docs/source/tutorial/mutations.md index 5dc6fc8..0c90c36 100644 --- a/docs/source/tutorial/mutations.md +++ b/docs/source/tutorial/mutations.md @@ -7,7 +7,7 @@ Time to accomplish: _12 Minutes_ With Apollo Client, updating data from a graph API is as simple as calling a function. Additionally, the Apollo Client cache is smart enough to automatically update in most cases. In this section, we'll learn how to use the `useMutation` Hook from React Apollo to login a user. -## What is the useMutation Hook? +## What is the useMutation hook? The `useMutation` Hook is another important building block in an Apollo app. It leverages React's [Hooks API](https://reactjs.org/docs/hooks-intro.html) to provide a function to execute a GraphQL mutation. Additionally, it tracks the loading, completion, and error state of that mutation. From 78185ebf18d25c6ef42147570077020e2ab90b5f Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Mon, 5 Aug 2019 13:17:37 -0400 Subject: [PATCH 13/25] Update docs/source/tutorial/mutations.md Co-Authored-By: Peggy Rayzis --- docs/source/tutorial/mutations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/mutations.md b/docs/source/tutorial/mutations.md index 0c90c36..12be925 100644 --- a/docs/source/tutorial/mutations.md +++ b/docs/source/tutorial/mutations.md @@ -9,7 +9,7 @@ With Apollo Client, updating data from a graph API is as simple as calling a fun ## What is the useMutation hook? -The `useMutation` Hook is another important building block in an Apollo app. It leverages React's [Hooks API](https://reactjs.org/docs/hooks-intro.html) to provide a function to execute a GraphQL mutation. Additionally, it tracks the loading, completion, and error state of that mutation. +The `useMutation` hook is another important building block in an Apollo app. It leverages React's [Hooks API](https://reactjs.org/docs/hooks-intro.html) to provide a function to execute a GraphQL mutation. Additionally, it tracks the loading, completion, and error state of that mutation. Updating data with a `useMutation` Hook from `@apollo/react-hooks` is very similar to fetching data with a `useQuery` Hook. The main difference is that the first value in the `useMutation` result tuple is a **mutate function** that actually triggers the mutation when it is called. The second value in the result tuple is a result object that contains loading and error state, as well as the return value from the mutation. Let's see an example: From 7c1d69bc83f9d214e849b4d1510e043f3f4b784b Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Mon, 5 Aug 2019 13:17:54 -0400 Subject: [PATCH 14/25] Update docs/source/tutorial/mutations.md Co-Authored-By: Peggy Rayzis --- docs/source/tutorial/mutations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/mutations.md b/docs/source/tutorial/mutations.md index 12be925..7e1be17 100644 --- a/docs/source/tutorial/mutations.md +++ b/docs/source/tutorial/mutations.md @@ -5,7 +5,7 @@ description: Learn how to update data with the useMutation hook Time to accomplish: _12 Minutes_ -With Apollo Client, updating data from a graph API is as simple as calling a function. Additionally, the Apollo Client cache is smart enough to automatically update in most cases. In this section, we'll learn how to use the `useMutation` Hook from React Apollo to login a user. +With Apollo Client, updating data from a graph API is as simple as calling a function. Additionally, the Apollo Client cache is smart enough to automatically update in most cases. In this section, we'll learn how to use the `useMutation` hook to login a user. ## What is the useMutation hook? From 114ec687edc911a4e91aadd7e9f48057e906d11f Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Mon, 5 Aug 2019 13:18:10 -0400 Subject: [PATCH 15/25] Update docs/source/tutorial/mutations.md Co-Authored-By: Peggy Rayzis --- docs/source/tutorial/mutations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/mutations.md b/docs/source/tutorial/mutations.md index 7e1be17..6df0232 100644 --- a/docs/source/tutorial/mutations.md +++ b/docs/source/tutorial/mutations.md @@ -11,7 +11,7 @@ With Apollo Client, updating data from a graph API is as simple as calling a fun The `useMutation` hook is another important building block in an Apollo app. It leverages React's [Hooks API](https://reactjs.org/docs/hooks-intro.html) to provide a function to execute a GraphQL mutation. Additionally, it tracks the loading, completion, and error state of that mutation. -Updating data with a `useMutation` Hook from `@apollo/react-hooks` is very similar to fetching data with a `useQuery` Hook. The main difference is that the first value in the `useMutation` result tuple is a **mutate function** that actually triggers the mutation when it is called. The second value in the result tuple is a result object that contains loading and error state, as well as the return value from the mutation. Let's see an example: +Updating data with a `useMutation` hook from `@apollo/react-hooks` is very similar to fetching data with a `useQuery` hook. The main difference is that the first value in the `useMutation` result tuple is a **mutate function** that actually triggers the mutation when it is called. The second value in the result tuple is a result object that contains loading and error state, as well as the return value from the mutation. Let's see an example: ## Update data with useMutation From dce5f7688c0fc4ac343df74e487e85c9bb2cdeab Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Mon, 5 Aug 2019 13:18:26 -0400 Subject: [PATCH 16/25] Update docs/source/tutorial/mutations.md Co-Authored-By: Peggy Rayzis --- docs/source/tutorial/mutations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/mutations.md b/docs/source/tutorial/mutations.md index 6df0232..d7e9f80 100644 --- a/docs/source/tutorial/mutations.md +++ b/docs/source/tutorial/mutations.md @@ -33,7 +33,7 @@ const LOGIN_USER = gql` `; ``` -Just like before, we're using the `gql` function to wrap our GraphQL mutation so it can be parsed into an AST. We're also importing some components that we'll use in the next steps. Now, let's bind this mutation to our component by passing it to the `useMutation` Hook: +Just like before, we're using the `gql` function to wrap our GraphQL mutation so it can be parsed into an AST. We're also importing some components that we'll use in the next steps. Now, let's bind this mutation to our component by passing it to the `useMutation` hook: _src/pages/login.js_ From dd2300d336e2a528b79d0dcaa4812cc99be8e903 Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Mon, 5 Aug 2019 13:18:39 -0400 Subject: [PATCH 17/25] Update docs/source/tutorial/mutations.md Co-Authored-By: Peggy Rayzis --- docs/source/tutorial/mutations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/mutations.md b/docs/source/tutorial/mutations.md index d7e9f80..018e55d 100644 --- a/docs/source/tutorial/mutations.md +++ b/docs/source/tutorial/mutations.md @@ -44,7 +44,7 @@ export default function Login() { } ``` -Our `useMutation` Hook returns a mutate function (`login`) and the data object returned from the mutation. Finally, we pass our login function to the `LoginForm` component. +Our `useMutation` hook returns a mutate function (`login`) and the data object returned from the mutation that we destructure from the tuple. Finally, we pass our login function to the `LoginForm` component. To create a better experience for our users, we want to persist the login between sessions. In order to do that, we need to save our login token to `localStorage`. Let's learn how we can use the `onCompleted` handler of `useMutation` to persist our login: From 9731bd8cedbe26e321d0461848c8f844f689b672 Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Mon, 5 Aug 2019 13:19:27 -0400 Subject: [PATCH 18/25] Update docs/source/tutorial/queries.md Co-Authored-By: Peggy Rayzis --- docs/source/tutorial/queries.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/queries.md b/docs/source/tutorial/queries.md index 3efd66a..0edf958 100644 --- a/docs/source/tutorial/queries.md +++ b/docs/source/tutorial/queries.md @@ -1,6 +1,6 @@ --- title: "6. Fetch data with queries" -description: Learn how to fetch data with the useQuery Hook +description: Learn how to fetch data with the useQuery hook --- Time to accomplish: _15 Minutes_ From db97b36ae0d977006402241dfc0b1ecf3ac7b703 Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Mon, 5 Aug 2019 13:19:37 -0400 Subject: [PATCH 19/25] Update docs/source/tutorial/queries.md Co-Authored-By: Peggy Rayzis --- docs/source/tutorial/queries.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/queries.md b/docs/source/tutorial/queries.md index 0edf958..ff305d6 100644 --- a/docs/source/tutorial/queries.md +++ b/docs/source/tutorial/queries.md @@ -7,7 +7,7 @@ description: Learn how to fetch data with the useQuery hook Apollo Client simplifies fetching data from a graph API because it intelligently caches your data, as well as tracks loading and error state. In the previous section, we learned how to fetch a sample query with Apollo Client without using a view integration. In this section, we'll learn how to use the `useQuery` Hook from `@apollo/react-hooks` to fetch more complex queries and execute features like pagination. -## The useQuery Hook +## The useQuery hook The `useQuery` Hook is one of the most important building blocks of an Apollo app. It's a React Hook that fetches a GraphQL query and exposes the result so you can render your UI based on the data it returns. From d96ff50bfc7dd160cfc5fb2bd69afb8a5d3c0208 Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Mon, 5 Aug 2019 13:19:46 -0400 Subject: [PATCH 20/25] Update docs/source/tutorial/queries.md Co-Authored-By: Peggy Rayzis --- docs/source/tutorial/queries.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/queries.md b/docs/source/tutorial/queries.md index ff305d6..d7967e4 100644 --- a/docs/source/tutorial/queries.md +++ b/docs/source/tutorial/queries.md @@ -9,7 +9,7 @@ Apollo Client simplifies fetching data from a graph API because it intelligently ## The useQuery hook -The `useQuery` Hook is one of the most important building blocks of an Apollo app. It's a React Hook that fetches a GraphQL query and exposes the result so you can render your UI based on the data it returns. +The `useQuery` hook is one of the most important building blocks of an Apollo app. It's a React Hook that fetches a GraphQL query and exposes the result so you can render your UI based on the data it returns. The `useQuery` Hook leverages React's [Hooks API](https://reactjs.org/docs/hooks-intro.html) to fetch and load data from queries into our UI. It exposes `error`, `loading` and `data` properties through a result object, that help us populate and render our component. Let's see an example: From 39b6fce198a290389ee043593dee0b8762a42e9d Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Mon, 5 Aug 2019 13:19:55 -0400 Subject: [PATCH 21/25] Update docs/source/tutorial/queries.md Co-Authored-By: Peggy Rayzis --- docs/source/tutorial/queries.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/queries.md b/docs/source/tutorial/queries.md index d7967e4..c1de905 100644 --- a/docs/source/tutorial/queries.md +++ b/docs/source/tutorial/queries.md @@ -274,7 +274,7 @@ Great, now we've successfully refactored our queries to use fragments. Fragments ### Customizing the fetch policy -Sometimes, it's useful to tell Apollo Client to bypass the cache altogether if you have some data that constantly needs to be refreshed. We can do this by customizing the `useQuery` Hook's `fetchPolicy`. +Sometimes, it's useful to tell Apollo Client to bypass the cache altogether if you have some data that constantly needs to be refreshed. We can do this by customizing the `useQuery` hook's `fetchPolicy`. First, let's navigate to `src/pages/profile.js` and write our query: From f9bc581ff602aae48cecc87eb8d1ec787fed6022 Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Mon, 5 Aug 2019 13:20:02 -0400 Subject: [PATCH 22/25] Update docs/source/tutorial/queries.md Co-Authored-By: Peggy Rayzis --- docs/source/tutorial/queries.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/queries.md b/docs/source/tutorial/queries.md index c1de905..2ff499f 100644 --- a/docs/source/tutorial/queries.md +++ b/docs/source/tutorial/queries.md @@ -78,7 +78,7 @@ export default function Launches() { } ``` -To render the list, we pass the `GET_LAUNCHES` query from the previous step into our `useQuery` Hook. Then, depending on the state of `loading`, `error`, and `data`, we either render a loading indicator, an error message, or a list of launches. +To render the list, we pass the `GET_LAUNCHES` query from the previous step into our `useQuery` hook. Then, depending on the state of `loading`, `error`, and `data`, we either render a loading indicator, an error message, or a list of launches. We're not done yet! Right now, this query is only fetching the first 20 launches from the list. To fetch the full list of launches, we need to build a pagination feature that displays a `Load More` button for loading more items on the screen. Let's learn how! From 0761a180e1853615b2b046285ea2e99581c83293 Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Mon, 5 Aug 2019 13:20:10 -0400 Subject: [PATCH 23/25] Update docs/source/tutorial/queries.md Co-Authored-By: Peggy Rayzis --- docs/source/tutorial/queries.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/queries.md b/docs/source/tutorial/queries.md index 2ff499f..34d7f0a 100644 --- a/docs/source/tutorial/queries.md +++ b/docs/source/tutorial/queries.md @@ -11,7 +11,7 @@ Apollo Client simplifies fetching data from a graph API because it intelligently The `useQuery` hook is one of the most important building blocks of an Apollo app. It's a React Hook that fetches a GraphQL query and exposes the result so you can render your UI based on the data it returns. -The `useQuery` Hook leverages React's [Hooks API](https://reactjs.org/docs/hooks-intro.html) to fetch and load data from queries into our UI. It exposes `error`, `loading` and `data` properties through a result object, that help us populate and render our component. Let's see an example: +The `useQuery` hook leverages React's [Hooks API](https://reactjs.org/docs/hooks-intro.html) to fetch and load data from queries into our UI. It exposes `error`, `loading` and `data` properties through a result object, that help us populate and render our component. Let's see an example: ## Fetching a list From 4be3987dd07620c14a255499422db99fd6e70a72 Mon Sep 17 00:00:00 2001 From: Hugh Willson Date: Mon, 5 Aug 2019 13:20:24 -0400 Subject: [PATCH 24/25] Update docs/source/tutorial/queries.md Co-Authored-By: Peggy Rayzis --- docs/source/tutorial/queries.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/queries.md b/docs/source/tutorial/queries.md index 34d7f0a..5e650c3 100644 --- a/docs/source/tutorial/queries.md +++ b/docs/source/tutorial/queries.md @@ -5,7 +5,7 @@ description: Learn how to fetch data with the useQuery hook Time to accomplish: _15 Minutes_ -Apollo Client simplifies fetching data from a graph API because it intelligently caches your data, as well as tracks loading and error state. In the previous section, we learned how to fetch a sample query with Apollo Client without using a view integration. In this section, we'll learn how to use the `useQuery` Hook from `@apollo/react-hooks` to fetch more complex queries and execute features like pagination. +Apollo Client simplifies fetching data from a graph API because it intelligently caches your data, as well as tracks loading and error state. In the previous section, we learned how to fetch a sample query with Apollo Client without using a view integration. In this section, we'll learn how to use the `useQuery` hook from `@apollo/react-hooks` to fetch more complex queries and execute features like pagination. ## The useQuery hook From 2fffdb6b533393e9bdbb49520e357d3eefd4d595 Mon Sep 17 00:00:00 2001 From: hwillson Date: Mon, 5 Aug 2019 13:35:16 -0400 Subject: [PATCH 25/25] Replace `ApolloConsumer` with `useApolloClient` --- docs/source/tutorial/local-state.md | 25 +++++++++++-------------- docs/source/tutorial/mutations.md | 25 +++++++++---------------- 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/docs/source/tutorial/local-state.md b/docs/source/tutorial/local-state.md index c297ab1..5d79d5c 100644 --- a/docs/source/tutorial/local-state.md +++ b/docs/source/tutorial/local-state.md @@ -231,26 +231,23 @@ _src/containers/logout-button.js_ ```jsx import React from 'react'; import styled from 'react-emotion'; -import { ApolloConsumer } from '@apollo/react-hooks'; +import { useApolloClient } from '@apollo/react-hooks'; import { menuItemClassName } from '../components/menu-item'; import { ReactComponent as ExitIcon } from '../assets/icons/exit.svg'; export default function LogoutButton() { + const client = useApolloClient(); return ( - - {client => ( - { - client.writeData({ data: { isLoggedIn: false } }); // highlight-line - localStorage.clear(); - }} - > - - Logout - - )} - + { + client.writeData({ data: { isLoggedIn: false } }); // highlight-line + localStorage.clear(); + }} + > + + Logout + ); } diff --git a/docs/source/tutorial/mutations.md b/docs/source/tutorial/mutations.md index 018e55d..1340398 100644 --- a/docs/source/tutorial/mutations.md +++ b/docs/source/tutorial/mutations.md @@ -21,7 +21,7 @@ _src/pages/login.js_ ```js import React from 'react'; -import { ApolloConsumer, useMutation } from '@apollo/react-hooks'; +import { useApolloClient, useMutation } from '@apollo/react-hooks'; import gql from 'graphql-tag'; import { LoginForm, Loading } from '../components'; @@ -48,18 +48,19 @@ Our `useMutation` hook returns a mutate function (`login`) and the data object r To create a better experience for our users, we want to persist the login between sessions. In order to do that, we need to save our login token to `localStorage`. Let's learn how we can use the `onCompleted` handler of `useMutation` to persist our login: -### Expose Apollo Client with ApolloConsumer +### Expose Apollo Client with useApolloClient -One of the main functions of React Apollo is that it puts your `ApolloClient` instance on React's context. Sometimes, we need to access the `ApolloClient` instance to directly call a method that isn't exposed by the `@apollo/react-hooks` helper components. The `ApolloConsumer` component can help us access the client. +One of the main functions of React Apollo is that it puts your `ApolloClient` instance on React's context. Sometimes, we need to access the `ApolloClient` instance to directly call a method that isn't exposed by the `@apollo/react-hooks` helper components. The `useApolloClient` hook can help us access the client. -`ApolloConsumer` takes a render prop function as a child that is called with the client instance. Let's wrap our `useMutation` based component with `ApolloConsumer` to expose the client. Next, we want to pass an `onCompleted` callback to `useMutation` that will be called once the mutation is complete with its return value. This callback is where we will save the login token to `localStorage`. +Let's call `useApolloClient` to get the currently configured client instance. Next, we want to pass an `onCompleted` callback to `useMutation` that will be called once the mutation is complete with its return value. This callback is where we will save the login token to `localStorage`. In our `onCompleted` handler, we also call `client.writeData` to write local data to the Apollo cache indicating that the user is logged in. This is an example of a **direct write** that we'll explore further in the next section on local state management. _src/pages/login.js_ -```jsx{5-8,13-14,22} +```jsx{2,6-9} export default function Login() { + const client = useApolloClient(); const [login, { loading, error }] = useMutation( LOGIN_USER, { @@ -70,18 +71,10 @@ export default function Login() { } ); - return ( - - {client => { - // this loading state will probably never show, but it's helpful to - // have for testing - if (loading) return ; - if (error) return

An error occurred

; + if (loading) return ; + if (error) return

An error occurred

; - return ; - }} -
- ); + return ; } ```