{"componentChunkName":"component---src-pages-tutorial-react-step-3-mdx","path":"/tutorial/react/step-3/","result":{"pageContext":{"isCreatedByStatefulCreatePages":true,"frontmatter":{"title":"3. Using APIs","description":"Welcome to Carbon! This tutorial will guide you in creating a React app with the Carbon Design System.","tabs":["Overview","Step 1","Step 2","Step 3","Step 4","Step 5","Wrapping up"]},"relativePagePath":"/tutorial/react/step-3.mdx","titleType":"prepend","MdxNode":{"id":"d83ecb20-6287-56db-ab04-6fcb0741e458","children":[],"parent":"3224ae70-9b33-5fc6-9871-6fe3a442bd87","internal":{"content":"---\ntitle: 3. Using APIs\ndescription: Welcome to Carbon! This tutorial will guide you in creating a React app with the Carbon Design System.\ntabs:\n  ['Overview', 'Step 1', 'Step 2', 'Step 3', 'Step 4', 'Step 5', 'Wrapping up']\n---\n\nimport Preview from 'components/Preview';\n\n### This step takes our static components and populates them with data from the GitHub GraphQL API – loading states and all. We'll be displaying Carbon repository information in a data table.\n\n<AnchorLinks>\n\n<AnchorLink>Fork, clone and branch</AnchorLink>\n<AnchorLink>Install dependencies</AnchorLink>\n<AnchorLink>Create access token</AnchorLink>\n<AnchorLink>Connect to Apollo</AnchorLink>\n<AnchorLink>Fetch data</AnchorLink>\n<AnchorLink>Populate data table</AnchorLink>\n<AnchorLink>Add loading</AnchorLink>\n<AnchorLink>Add pagination</AnchorLink>\n<AnchorLink>Submit pull request</AnchorLink>\n\n</AnchorLinks>\n\n### Preview\n\nThe [GitHub GraphQL API](https://developer.github.com/v4/) is very well documented, and even though the focus of this tutorial isn't learning and using GraphQL, it's a great opportunity to fetch Carbon-related data for this Carbon tutorial.\n\nTo do so, we'll be using Apollo Client, the front-end component of the [Apollo Platform](https://www.apollographql.com/docs/intro/platform). Apollo provides several open source tools for using GraphQL throughout your application’s stack. Apollo Client is a sophisticated GraphQL client that manages data and state in an application.\n\nA [preview](https://react-step-4--carbon-tutorial.netlify.com) of what you will build (see repositories page):\n\n<Preview\n  height=\"400\"\n  title=\"Carbon Tutorial Step 3\"\n  src=\"https://react-step-4--carbon-tutorial.netlify.com\"\n  frameborder=\"no\"\n  allowtransparency=\"true\"\n  allowfullscreen=\"true\"\n/>\n\n## Fork, clone and branch\n\nThis tutorial has an accompanying GitHub repository called [carbon-tutorial](https://github.com/carbon-design-system/carbon-tutorial) that we'll use as a starting point for each step. If you haven't forked and cloned that repository yet, and haven't added the upstream remote, go ahead and do so by following the [step 1 instructions](/tutorial/react/step-1#fork-clone--branch).\n\n### Branch\n\nWith your repository all set up, let's check out the branch for this tutorial step's starting point.\n\n```bash\n$ git fetch upstream\n$ git checkout -b react-step-3 upstream/react-step-3\n```\n\n### Build and start app\n\nInstall the app's dependencies:\n\n```bash\n$ yarn\n```\n\nThen, start the app:\n\n```bash\n$ yarn start\n```\n\nYou should see something similar to where the [previous step](/tutorial/react/step-2) left off. Stop your app with `CTRL-C` and let's get everything installed.\n\n## Install dependencies\n\nWe'll need to install three new dependencies to incorporate Apollo into our application.\n\n- `apollo-boost` - package containing everything you need to set up Apollo Client\n- `graphql` - parses your GraphQL queries\n- `react-apollo` - Apollo integration for React\n\nInstall them with the command:\n\n```bash\n$ yarn add apollo-boost graphql react-apollo\n```\n\n## Create access token\n\nYou'll need a personal access token from your GitHub account in order to make requests to the GitHub API. Check out [this guide](https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line) to see how to get one.\n\nWhen you get to the scope/permissions step, you can leave them all unchecked. We don't need any special permissions, we just need access to the public API.\n\nOnce you have your token, we need to put it in a place where create-react-app can use it. When your application is being built and developed, create-react-app will parse environmental variables in any file that starts with `.env` and make them available under `process.env.MY_VARIABLE`.\n\nOne caveat is that we need to start our variables with `REACT_APP_`. You can read more about environmental variables in [create-react-app's guide](https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables).\n\nSince we don't want to commit this file to Git, we can put it in `.env.local` which is in our `.gitignore` list. Your file should just have a single line like this one, where the `x`s are replaced with your unique token.\n\n```bash path=.env.local\nREACT_APP_GITHUB_PERSONAL_ACCESS_TOKEN=xxxxxx\n```\n\nGo ahead and start your app with `yarn start`, or, if your app is running, you'll need to restart it to get access to this token.\n\n## Connect to Apollo\n\nThe `react-apollo` library gives us a component that we need to put at the base of our application. Typically the best place for things that need to wrap the entire application is at the root of the application. For us, that's at `src/index.js`.\n\nAdd these two imports to `src/index.js`:\n\n```javascript path=src/index.js\nimport ApolloClient from 'apollo-boost';\nimport { ApolloProvider } from 'react-apollo';\n```\n\nNext, make your client by providing a URI for the GitHub GraphQL API as well as an authorization header using the environmental variable you just added to `.env.local`.\n\n```javascript path=src/index.js\nconst client = new ApolloClient({\n  uri: 'https://api.github.com/graphql',\n  headers: {\n    authorization: `Bearer ${process.env.REACT_APP_GITHUB_PERSONAL_ACCESS_TOKEN}`,\n  },\n});\n```\n\nNow we can wrap our application with `ApolloProvider`. At the same time, we'll pass in the client we just made as a prop to the `ApolloProvider` component. Replace:\n\n```html path=src/index.js\n<Router>\n  <App />\n</Router>\n```\n\nWith:\n\n<!-- prettier-ignore-start -->\n```html path=src/index.js\n<ApolloProvider client={client}>\n  <Router>\n    <App />\n  </Router>\n</ApolloProvider>\n```\n<!-- prettier-ignore-end -->\n\n## Fetch data\n\n### Imports\n\nAdd the following imports at the top of `RepoPage.js`:\n\n```javascript path=src/content/RepoPage/RepoPage.js\nimport { gql } from 'apollo-boost';\nimport { Query } from 'react-apollo';\n```\n\n### Query\n\nNext we'll assemble our GraphQL query to fetch only the data we need from the GraphQL API. We'll do this using the `gql` helper we just imported. The `gql` helper lets you write GraphQL queries using interpolated strings (backticks) in JavaScript. In addition, we'll be using the `Query` component from `react-apollo` which gives us some great information about our query's loading state in addition to the data.\n\nYou can use GitHub's [explorer](https://developer.github.com/v4/explorer/) tool to write and test your own queries. Try copying the query below and experiment with changing the properties. You can also click the \"Docs\" button in the top right of the explorer to view all of the available data and query parameters.\n\nIf you'd like some more information regarding writing queries and using the Query component, we recommend [Apollo's documentation](https://www.apollographql.com/docs/tutorial/queries) on this topic.\n\nAdd this after your imports:\n\n```graphql path=src/content/RepoPage/RepoPage.js\nconst REPO_QUERY = gql`\n  query REPO_QUERY {\n    # Let's use carbon as our organization\n    organization(login: \"carbon-design-system\") {\n      # We'll grab all the repositories in one go. To load more resources\n      # continuously, see the advanced topics.\n      repositories(first: 75, orderBy: { field: UPDATED_AT, direction: DESC }) {\n        totalCount\n        nodes {\n          url\n          homepageUrl\n          issues(filterBy: { states: OPEN }) {\n            totalCount\n          }\n          stargazers {\n            totalCount\n          }\n          releases(first: 1) {\n            totalCount\n            nodes {\n              name\n            }\n          }\n          name\n          updatedAt\n          createdAt\n          description\n          id\n        }\n      }\n    }\n  }\n`;\n```\n\n### Helpers\n\nBelow that, we should have our table headers set in a previous step that are good to go. Let's also keep our example rows below that.\n\nOur last column in the data table will be a comma-separated list of repository and home page links, so let's create a component called `LinkList`.\n\nImport `Link` at the top of `RepoPage.js`.\n\n```javascript path=src/content/RepoPage/RepoPage.js\nimport { Link } from 'carbon-components-react';\n```\n\nThen use `Link` in this component that has two props (`url` and `homepageUrl`) and returns an unordered list. If the repository does not have a home page URL, only render the repository link.\n\n```javascript path=src/content/RepoPage/RepoPage.js\nconst LinkList = ({ url, homepageUrl }) => (\n  <ul style={{ display: 'flex' }}>\n    <li>\n      <Link href={url}>GitHub</Link>\n    </li>\n    {homepageUrl && (\n      <li>\n        <span>&nbsp;|&nbsp;</span>\n        <Link href={homepageUrl}>Homepage</Link>\n      </li>\n    )}\n  </ul>\n);\n```\n\nAs a final helper, let's create a function that transforms row data to our expected header keys. Notice how we're using our new `LinkList` component to generate the value of the `links` key in each row.\n\n```javascript path=src/content/RepoPage/RepoPage.js\nconst getRowItems = rows =>\n  rows.map(row => ({\n    ...row,\n    key: row.id,\n    stars: row.stargazers.totalCount,\n    issueCount: row.issues.totalCount,\n    createdAt: new Date(row.createdAt).toLocaleDateString(),\n    updatedAt: new Date(row.updatedAt).toLocaleDateString(),\n    links: <LinkList url={row.url} homepageUrl={row.homepageUrl} />,\n  }));\n```\n\n### Query component\n\nAt this point, we should run our query and `console.log()` the results to verify that the request is working.\n\nThe `Query` component from `react-apollo` lets us render different content based on the state of our request. When `loading` is true, we'll render `Loading...` for the time being. If there's an issue, we'll render the corresponding error message.\n\nFinally, if neither of those are true, it means we have our data! One nice advantage of GraphQL is that as long as there are no errors, we can be certain the properties on the data we requested aren't `undefined`.\n\nWe need to render the `RepoTable` in `Query`'s `return()` statement once the request is no longer loading and when there are no errors. To do so, replace the `RepoTable` line with the following `Query`.\n\n```javascript path=src/content/RepoPage/RepoPage.js\n<RepoTable headers={headers} rows={rows} />\n```\n\nNotice how we're passing the `REPO_QUERY` that we previously defined into the `query` prop.\n\n```javascript path=src/content/RepoPage/RepoPage.js\n<Query query={REPO_QUERY}>\n  {({ loading, error, data: { organization } }) => {\n    // Wait for the request to complete\n    if (loading) return 'Loading...';\n\n    // Something went wrong with the data fetching\n    if (error) return `Error! ${error.message}`;\n\n    // If we're here, we've got our data!\n    console.log(organization);\n\n    return (\n      <>\n        <RepoTable headers={headers} rows={rows} />\n      </>\n    );\n  }}\n</Query>\n```\n\nThe page will look the same as we're still rendering our static example rows, but if you view your browser's console (e.g. [Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/)), you should see the response from GitHub!\n\n## Populate data table\n\nNow that we have that data, let's populate the data table. Replace `console.log(organization);` with the following that destructures the `organization` object. Once we have the repositories, we can call our `getRowItems()` helper to build the data table rows.\n\n```javascript path=src/content/RepoPage/RepoPage.js\n// If we're here, we've got our data!\nconst { repositories } = organization;\nconst rows = getRowItems(repositories.nodes);\n```\n\nThen, towards the top of `RepoPage.js` delete the `rows` array because we no longer need the example rows.\n\n### Render repository descriptions\n\nThe data table component and its pieces use a common React pattern called [render props](https://reactjs.org/docs/render-props.html). This a really powerful way for libraries to give developers control of rendering and manipulating their data.\n\nRevisiting `RepoTable.js`, we are already passing in our row objects along with headers for each column. The `render` prop is being used to tell the data table how to render the headers and rows. That prop takes a function that receives the processed headers and rows as arguments as well as some helper functions for rendering the table.\n\nOne common hurdle with the data table is how to access data that might not correspond with a table column but is needed to compute the value of a cell that does. The data table component processes and controls only the row properties which corresponds to headers (columns). Because of this, the `rows` object you get access to in the render prop function is _different_ than the one you passed in to the `rows` prop.\n\nWe need to modify one aspect of the data table because if you expand a row, it says `Row description`. We want to update that with the repository description coming from the GitHub API. This is an example of where we need a simple look-up function to find the data we care about - data that does not directly correspond to a column.\n\nTo do so, in `RepoTable.js`, add this look-up function as the first lines inside the `RepoTable`. This should go immediately before the component's `return()`.\n\n```javascript path=src/content/RepoPage/RepoTable.js\nconst getRowDescription = rowId => {\n  const row = rows.find(({ id }) => id === rowId);\n  return row ? row.description : '';\n};\n```\n\nFinally, in `RepoTable.js`, replace `<p>Row description</p>` with:\n\n```html path=src/content/RepoPage/RepoTable.js\n<p>{getRowDescription(row.id)}</p>\n```\n\n## Add loading\n\nAt this point, the first time that you visit the repositories page, we're querying the GitHub API and rendering the response through the `DataTable` component. We could stop here, but there's more to be done! Let's replace the `Loading...` string with the [DataTableSkeleton component](http://react.carbondesignsystem.com/?selectedKind=DataTableSkeleton).\n\nTo do so, back to `RepoPage.js`, add the `DataTableSkeleton` import by modifying the existing `carbon-components-react` import.\n\n```javascript path=src/content/RepoPage/RepoPage.js\nimport { Link, DataTableSkeleton } from 'carbon-components-react';\n```\n\nThen replace the `if (loading) return 'Loading...';` with:\n\n```javascript path=src/content/RepoPage/RepoPage.js\nif (loading)\n  return (\n    <DataTableSkeleton\n      columnCount={headers.length + 1}\n      rowCount={10}\n      headers={headers}\n    />\n  );\n```\n\nWe need to tell the loading skeleton how many rows to render, so let's use 10 skeleton rows to prepare for the next enhancement...\n\n## Add pagination\n\nPagination! Instead of rendering every repository, let's add pagination to the data table to only render 10 at a time. Depending on your specific requirements, you may need to fetch new data each time that you interact with the pagination component, but for simplicity, we're going to make one request to fetch all data, and then paginate the in-memory row data.\n\nWe'll be using [React Hooks](https://reactjs.org/docs/hooks-intro.html) to manage our state. Hooks are a relatively new React API that allows us to author a React component's stateful logic in a function component rather than a class component. Using hooks means we don't need to worry about complex lifecycle methods.\n\nImport React's [useState](https://reactjs.org/docs/hooks-state.html) by modifying the `React` import.\n\n```javascript path=src/content/RepoPage/RepoPage.js\nimport React, { useState } from 'react';\n```\n\nThen initialize the new state variables that we'll use for pagination as the first lines inside the `RepoPage` component, above the `return()`.\n\n```javascript path=src/content/RepoPage/RepoPage.js\nconst [totalItems, setTotalItems] = useState(0);\nconst [firstRowIndex, setFirstRowIndex] = useState(0);\nconst [currentPageSize, setCurrentPageSize] = useState(10);\n```\n\nThis initializes the total number of rows and the index of the first row to `0`, and the page size to `10` as we also specified in our loading skeleton.\n\nNext we need to use the function that updates the `totalItems` state, `setTotalItems()`, after we destructure our `organization.repositories`. Your block that transforms row data should look like:\n\n```javascript path=src/content/RepoPage/RepoPage.js\n// If we're here, we've got our data!\nconst { repositories } = organization;\nsetTotalItems(repositories.totalCount);\nconst rows = getRowItems(repositories.nodes);\n```\n\nThen we need to update our `RepoTable` `rows` prop to only render the subset of rows for the current \"page\". Update `<RepoTable headers={headers} rows={rows} />` to:\n\n<!-- prettier-ignore-start -->\n```javascript path=src/content/RepoPage/RepoPage.js\n<RepoTable\n  headers={headers}\n  rows={rows.slice(\n    firstRowIndex,\n    firstRowIndex + currentPageSize\n  )}\n/>\n```\n<!-- prettier-ignore-end -->\n\n_Note: We only pass the rows that we want our table to display. We can do this by slicing the our array of rows depending on the first item and the page size._\n\nFinally, let's add the `Pagination` to update our state variables and cause the data table to render new rows.\n\nImport `Pagination` by updating the `carbon-components-react` import.\n\n```javascript path=src/content/RepoPage/RepoPage.js\nimport { Link, DataTableSkeleton, Pagination } from 'carbon-components-react';\n```\n\nImmediately after the `RepoTable` closing tag (`/>`), add the `Pagination` component using the state variables that we previously initialized.\n\n```javascript path=src/content/RepoPage/RepoPage.js\n<Pagination\n  totalItems={totalItems}\n  backwardText=\"Previous page\"\n  forwardText=\"Next page\"\n  pageSize={currentPageSize}\n  pageSizes={[5, 10, 15, 25]}\n  itemsPerPageText=\"Items per page\"\n  onChange={({ page, pageSize }) => {\n    if (pageSize !== currentPageSize) {\n      setCurrentPageSize(pageSize);\n    }\n    setFirstRowIndex(pageSize * (page - 1));\n  }}\n/>\n```\n\n_Note: The_ `Pagination` _component isn't inherently connected in any way to the_ `DataTable` _- we need to tell it what to do when a change occurs using the_ `onChange` _prop. This includes both page size changes and displaying different rows._\n\n_Note: Like the other Carbon React components,_ `Pagination` _component examples can be found in [Storybook](http://react.carbondesignsystem.com/?selectedKind=Pagination) by browsing the story and knobs._\n\nThat does it! Your data table should fetch GitHub data on first render. You can expand each row to see the repository's description. You can modify the pagination items per page and cycle through pages or jump to a specific page of repositories.\n\n## Submit pull request\n\nWe're going to submit a pull request to verify completion of this tutorial step.\n\n### Continuous integration (CI) check\n\nRun the CI check to make sure we're all set to submit a pull request.\n\n```bash\n$ yarn ci-check\n```\n\n_Note: Having issues running the CI check? [Step 1](</tutorial/react/step-1#continuous-integration-(ci)-check>) has troubleshooting notes that may help._\n\n### Git commit and push\n\nBefore we can create a pull request, stage and commit all of your changes:\n\n```bash\n$ git add --all && git commit -m \"feat(tutorial): complete step 3\"\n```\n\nThen, push to your repository:\n\n```bash\n$ git push origin react-step-3\n```\n\n_Note: Having issues pushing your changes? [Step 1](/tutorial/react/step-1#git-commit-and-push) has troubleshooting notes that may help._\n\n### Pull request (PR)\n\nFinally, visit [carbon-tutorial](https://github.com/carbon-design-system/carbon-tutorial) to \"Compare & pull request\". In doing so, make sure that you are comparing to `react-step-3` into `base: react-step-3`.\n\n_Note: Expect your tutorial step PRs to be reviewed by the Carbon team but not merged. We'll close your PR so we can keep the repository's remote branches pristine and ready for the next person!_\n","type":"Mdx","contentDigest":"4b3def1a26dd7356da96e861475f7244","counter":1510,"owner":"gatsby-plugin-mdx"},"frontmatter":{"title":"3. Using APIs","description":"Welcome to Carbon! This tutorial will guide you in creating a React app with the Carbon Design System.","tabs":["Overview","Step 1","Step 2","Step 3","Step 4","Step 5","Wrapping up"]},"exports":{},"rawBody":"---\ntitle: 3. Using APIs\ndescription: Welcome to Carbon! This tutorial will guide you in creating a React app with the Carbon Design System.\ntabs:\n  ['Overview', 'Step 1', 'Step 2', 'Step 3', 'Step 4', 'Step 5', 'Wrapping up']\n---\n\nimport Preview from 'components/Preview';\n\n### This step takes our static components and populates them with data from the GitHub GraphQL API – loading states and all. We'll be displaying Carbon repository information in a data table.\n\n<AnchorLinks>\n\n<AnchorLink>Fork, clone and branch</AnchorLink>\n<AnchorLink>Install dependencies</AnchorLink>\n<AnchorLink>Create access token</AnchorLink>\n<AnchorLink>Connect to Apollo</AnchorLink>\n<AnchorLink>Fetch data</AnchorLink>\n<AnchorLink>Populate data table</AnchorLink>\n<AnchorLink>Add loading</AnchorLink>\n<AnchorLink>Add pagination</AnchorLink>\n<AnchorLink>Submit pull request</AnchorLink>\n\n</AnchorLinks>\n\n### Preview\n\nThe [GitHub GraphQL API](https://developer.github.com/v4/) is very well documented, and even though the focus of this tutorial isn't learning and using GraphQL, it's a great opportunity to fetch Carbon-related data for this Carbon tutorial.\n\nTo do so, we'll be using Apollo Client, the front-end component of the [Apollo Platform](https://www.apollographql.com/docs/intro/platform). Apollo provides several open source tools for using GraphQL throughout your application’s stack. Apollo Client is a sophisticated GraphQL client that manages data and state in an application.\n\nA [preview](https://react-step-4--carbon-tutorial.netlify.com) of what you will build (see repositories page):\n\n<Preview\n  height=\"400\"\n  title=\"Carbon Tutorial Step 3\"\n  src=\"https://react-step-4--carbon-tutorial.netlify.com\"\n  frameborder=\"no\"\n  allowtransparency=\"true\"\n  allowfullscreen=\"true\"\n/>\n\n## Fork, clone and branch\n\nThis tutorial has an accompanying GitHub repository called [carbon-tutorial](https://github.com/carbon-design-system/carbon-tutorial) that we'll use as a starting point for each step. If you haven't forked and cloned that repository yet, and haven't added the upstream remote, go ahead and do so by following the [step 1 instructions](/tutorial/react/step-1#fork-clone--branch).\n\n### Branch\n\nWith your repository all set up, let's check out the branch for this tutorial step's starting point.\n\n```bash\n$ git fetch upstream\n$ git checkout -b react-step-3 upstream/react-step-3\n```\n\n### Build and start app\n\nInstall the app's dependencies:\n\n```bash\n$ yarn\n```\n\nThen, start the app:\n\n```bash\n$ yarn start\n```\n\nYou should see something similar to where the [previous step](/tutorial/react/step-2) left off. Stop your app with `CTRL-C` and let's get everything installed.\n\n## Install dependencies\n\nWe'll need to install three new dependencies to incorporate Apollo into our application.\n\n- `apollo-boost` - package containing everything you need to set up Apollo Client\n- `graphql` - parses your GraphQL queries\n- `react-apollo` - Apollo integration for React\n\nInstall them with the command:\n\n```bash\n$ yarn add apollo-boost graphql react-apollo\n```\n\n## Create access token\n\nYou'll need a personal access token from your GitHub account in order to make requests to the GitHub API. Check out [this guide](https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line) to see how to get one.\n\nWhen you get to the scope/permissions step, you can leave them all unchecked. We don't need any special permissions, we just need access to the public API.\n\nOnce you have your token, we need to put it in a place where create-react-app can use it. When your application is being built and developed, create-react-app will parse environmental variables in any file that starts with `.env` and make them available under `process.env.MY_VARIABLE`.\n\nOne caveat is that we need to start our variables with `REACT_APP_`. You can read more about environmental variables in [create-react-app's guide](https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables).\n\nSince we don't want to commit this file to Git, we can put it in `.env.local` which is in our `.gitignore` list. Your file should just have a single line like this one, where the `x`s are replaced with your unique token.\n\n```bash path=.env.local\nREACT_APP_GITHUB_PERSONAL_ACCESS_TOKEN=xxxxxx\n```\n\nGo ahead and start your app with `yarn start`, or, if your app is running, you'll need to restart it to get access to this token.\n\n## Connect to Apollo\n\nThe `react-apollo` library gives us a component that we need to put at the base of our application. Typically the best place for things that need to wrap the entire application is at the root of the application. For us, that's at `src/index.js`.\n\nAdd these two imports to `src/index.js`:\n\n```javascript path=src/index.js\nimport ApolloClient from 'apollo-boost';\nimport { ApolloProvider } from 'react-apollo';\n```\n\nNext, make your client by providing a URI for the GitHub GraphQL API as well as an authorization header using the environmental variable you just added to `.env.local`.\n\n```javascript path=src/index.js\nconst client = new ApolloClient({\n  uri: 'https://api.github.com/graphql',\n  headers: {\n    authorization: `Bearer ${process.env.REACT_APP_GITHUB_PERSONAL_ACCESS_TOKEN}`,\n  },\n});\n```\n\nNow we can wrap our application with `ApolloProvider`. At the same time, we'll pass in the client we just made as a prop to the `ApolloProvider` component. Replace:\n\n```html path=src/index.js\n<Router>\n  <App />\n</Router>\n```\n\nWith:\n\n<!-- prettier-ignore-start -->\n```html path=src/index.js\n<ApolloProvider client={client}>\n  <Router>\n    <App />\n  </Router>\n</ApolloProvider>\n```\n<!-- prettier-ignore-end -->\n\n## Fetch data\n\n### Imports\n\nAdd the following imports at the top of `RepoPage.js`:\n\n```javascript path=src/content/RepoPage/RepoPage.js\nimport { gql } from 'apollo-boost';\nimport { Query } from 'react-apollo';\n```\n\n### Query\n\nNext we'll assemble our GraphQL query to fetch only the data we need from the GraphQL API. We'll do this using the `gql` helper we just imported. The `gql` helper lets you write GraphQL queries using interpolated strings (backticks) in JavaScript. In addition, we'll be using the `Query` component from `react-apollo` which gives us some great information about our query's loading state in addition to the data.\n\nYou can use GitHub's [explorer](https://developer.github.com/v4/explorer/) tool to write and test your own queries. Try copying the query below and experiment with changing the properties. You can also click the \"Docs\" button in the top right of the explorer to view all of the available data and query parameters.\n\nIf you'd like some more information regarding writing queries and using the Query component, we recommend [Apollo's documentation](https://www.apollographql.com/docs/tutorial/queries) on this topic.\n\nAdd this after your imports:\n\n```graphql path=src/content/RepoPage/RepoPage.js\nconst REPO_QUERY = gql`\n  query REPO_QUERY {\n    # Let's use carbon as our organization\n    organization(login: \"carbon-design-system\") {\n      # We'll grab all the repositories in one go. To load more resources\n      # continuously, see the advanced topics.\n      repositories(first: 75, orderBy: { field: UPDATED_AT, direction: DESC }) {\n        totalCount\n        nodes {\n          url\n          homepageUrl\n          issues(filterBy: { states: OPEN }) {\n            totalCount\n          }\n          stargazers {\n            totalCount\n          }\n          releases(first: 1) {\n            totalCount\n            nodes {\n              name\n            }\n          }\n          name\n          updatedAt\n          createdAt\n          description\n          id\n        }\n      }\n    }\n  }\n`;\n```\n\n### Helpers\n\nBelow that, we should have our table headers set in a previous step that are good to go. Let's also keep our example rows below that.\n\nOur last column in the data table will be a comma-separated list of repository and home page links, so let's create a component called `LinkList`.\n\nImport `Link` at the top of `RepoPage.js`.\n\n```javascript path=src/content/RepoPage/RepoPage.js\nimport { Link } from 'carbon-components-react';\n```\n\nThen use `Link` in this component that has two props (`url` and `homepageUrl`) and returns an unordered list. If the repository does not have a home page URL, only render the repository link.\n\n```javascript path=src/content/RepoPage/RepoPage.js\nconst LinkList = ({ url, homepageUrl }) => (\n  <ul style={{ display: 'flex' }}>\n    <li>\n      <Link href={url}>GitHub</Link>\n    </li>\n    {homepageUrl && (\n      <li>\n        <span>&nbsp;|&nbsp;</span>\n        <Link href={homepageUrl}>Homepage</Link>\n      </li>\n    )}\n  </ul>\n);\n```\n\nAs a final helper, let's create a function that transforms row data to our expected header keys. Notice how we're using our new `LinkList` component to generate the value of the `links` key in each row.\n\n```javascript path=src/content/RepoPage/RepoPage.js\nconst getRowItems = rows =>\n  rows.map(row => ({\n    ...row,\n    key: row.id,\n    stars: row.stargazers.totalCount,\n    issueCount: row.issues.totalCount,\n    createdAt: new Date(row.createdAt).toLocaleDateString(),\n    updatedAt: new Date(row.updatedAt).toLocaleDateString(),\n    links: <LinkList url={row.url} homepageUrl={row.homepageUrl} />,\n  }));\n```\n\n### Query component\n\nAt this point, we should run our query and `console.log()` the results to verify that the request is working.\n\nThe `Query` component from `react-apollo` lets us render different content based on the state of our request. When `loading` is true, we'll render `Loading...` for the time being. If there's an issue, we'll render the corresponding error message.\n\nFinally, if neither of those are true, it means we have our data! One nice advantage of GraphQL is that as long as there are no errors, we can be certain the properties on the data we requested aren't `undefined`.\n\nWe need to render the `RepoTable` in `Query`'s `return()` statement once the request is no longer loading and when there are no errors. To do so, replace the `RepoTable` line with the following `Query`.\n\n```javascript path=src/content/RepoPage/RepoPage.js\n<RepoTable headers={headers} rows={rows} />\n```\n\nNotice how we're passing the `REPO_QUERY` that we previously defined into the `query` prop.\n\n```javascript path=src/content/RepoPage/RepoPage.js\n<Query query={REPO_QUERY}>\n  {({ loading, error, data: { organization } }) => {\n    // Wait for the request to complete\n    if (loading) return 'Loading...';\n\n    // Something went wrong with the data fetching\n    if (error) return `Error! ${error.message}`;\n\n    // If we're here, we've got our data!\n    console.log(organization);\n\n    return (\n      <>\n        <RepoTable headers={headers} rows={rows} />\n      </>\n    );\n  }}\n</Query>\n```\n\nThe page will look the same as we're still rendering our static example rows, but if you view your browser's console (e.g. [Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/)), you should see the response from GitHub!\n\n## Populate data table\n\nNow that we have that data, let's populate the data table. Replace `console.log(organization);` with the following that destructures the `organization` object. Once we have the repositories, we can call our `getRowItems()` helper to build the data table rows.\n\n```javascript path=src/content/RepoPage/RepoPage.js\n// If we're here, we've got our data!\nconst { repositories } = organization;\nconst rows = getRowItems(repositories.nodes);\n```\n\nThen, towards the top of `RepoPage.js` delete the `rows` array because we no longer need the example rows.\n\n### Render repository descriptions\n\nThe data table component and its pieces use a common React pattern called [render props](https://reactjs.org/docs/render-props.html). This a really powerful way for libraries to give developers control of rendering and manipulating their data.\n\nRevisiting `RepoTable.js`, we are already passing in our row objects along with headers for each column. The `render` prop is being used to tell the data table how to render the headers and rows. That prop takes a function that receives the processed headers and rows as arguments as well as some helper functions for rendering the table.\n\nOne common hurdle with the data table is how to access data that might not correspond with a table column but is needed to compute the value of a cell that does. The data table component processes and controls only the row properties which corresponds to headers (columns). Because of this, the `rows` object you get access to in the render prop function is _different_ than the one you passed in to the `rows` prop.\n\nWe need to modify one aspect of the data table because if you expand a row, it says `Row description`. We want to update that with the repository description coming from the GitHub API. This is an example of where we need a simple look-up function to find the data we care about - data that does not directly correspond to a column.\n\nTo do so, in `RepoTable.js`, add this look-up function as the first lines inside the `RepoTable`. This should go immediately before the component's `return()`.\n\n```javascript path=src/content/RepoPage/RepoTable.js\nconst getRowDescription = rowId => {\n  const row = rows.find(({ id }) => id === rowId);\n  return row ? row.description : '';\n};\n```\n\nFinally, in `RepoTable.js`, replace `<p>Row description</p>` with:\n\n```html path=src/content/RepoPage/RepoTable.js\n<p>{getRowDescription(row.id)}</p>\n```\n\n## Add loading\n\nAt this point, the first time that you visit the repositories page, we're querying the GitHub API and rendering the response through the `DataTable` component. We could stop here, but there's more to be done! Let's replace the `Loading...` string with the [DataTableSkeleton component](http://react.carbondesignsystem.com/?selectedKind=DataTableSkeleton).\n\nTo do so, back to `RepoPage.js`, add the `DataTableSkeleton` import by modifying the existing `carbon-components-react` import.\n\n```javascript path=src/content/RepoPage/RepoPage.js\nimport { Link, DataTableSkeleton } from 'carbon-components-react';\n```\n\nThen replace the `if (loading) return 'Loading...';` with:\n\n```javascript path=src/content/RepoPage/RepoPage.js\nif (loading)\n  return (\n    <DataTableSkeleton\n      columnCount={headers.length + 1}\n      rowCount={10}\n      headers={headers}\n    />\n  );\n```\n\nWe need to tell the loading skeleton how many rows to render, so let's use 10 skeleton rows to prepare for the next enhancement...\n\n## Add pagination\n\nPagination! Instead of rendering every repository, let's add pagination to the data table to only render 10 at a time. Depending on your specific requirements, you may need to fetch new data each time that you interact with the pagination component, but for simplicity, we're going to make one request to fetch all data, and then paginate the in-memory row data.\n\nWe'll be using [React Hooks](https://reactjs.org/docs/hooks-intro.html) to manage our state. Hooks are a relatively new React API that allows us to author a React component's stateful logic in a function component rather than a class component. Using hooks means we don't need to worry about complex lifecycle methods.\n\nImport React's [useState](https://reactjs.org/docs/hooks-state.html) by modifying the `React` import.\n\n```javascript path=src/content/RepoPage/RepoPage.js\nimport React, { useState } from 'react';\n```\n\nThen initialize the new state variables that we'll use for pagination as the first lines inside the `RepoPage` component, above the `return()`.\n\n```javascript path=src/content/RepoPage/RepoPage.js\nconst [totalItems, setTotalItems] = useState(0);\nconst [firstRowIndex, setFirstRowIndex] = useState(0);\nconst [currentPageSize, setCurrentPageSize] = useState(10);\n```\n\nThis initializes the total number of rows and the index of the first row to `0`, and the page size to `10` as we also specified in our loading skeleton.\n\nNext we need to use the function that updates the `totalItems` state, `setTotalItems()`, after we destructure our `organization.repositories`. Your block that transforms row data should look like:\n\n```javascript path=src/content/RepoPage/RepoPage.js\n// If we're here, we've got our data!\nconst { repositories } = organization;\nsetTotalItems(repositories.totalCount);\nconst rows = getRowItems(repositories.nodes);\n```\n\nThen we need to update our `RepoTable` `rows` prop to only render the subset of rows for the current \"page\". Update `<RepoTable headers={headers} rows={rows} />` to:\n\n<!-- prettier-ignore-start -->\n```javascript path=src/content/RepoPage/RepoPage.js\n<RepoTable\n  headers={headers}\n  rows={rows.slice(\n    firstRowIndex,\n    firstRowIndex + currentPageSize\n  )}\n/>\n```\n<!-- prettier-ignore-end -->\n\n_Note: We only pass the rows that we want our table to display. We can do this by slicing the our array of rows depending on the first item and the page size._\n\nFinally, let's add the `Pagination` to update our state variables and cause the data table to render new rows.\n\nImport `Pagination` by updating the `carbon-components-react` import.\n\n```javascript path=src/content/RepoPage/RepoPage.js\nimport { Link, DataTableSkeleton, Pagination } from 'carbon-components-react';\n```\n\nImmediately after the `RepoTable` closing tag (`/>`), add the `Pagination` component using the state variables that we previously initialized.\n\n```javascript path=src/content/RepoPage/RepoPage.js\n<Pagination\n  totalItems={totalItems}\n  backwardText=\"Previous page\"\n  forwardText=\"Next page\"\n  pageSize={currentPageSize}\n  pageSizes={[5, 10, 15, 25]}\n  itemsPerPageText=\"Items per page\"\n  onChange={({ page, pageSize }) => {\n    if (pageSize !== currentPageSize) {\n      setCurrentPageSize(pageSize);\n    }\n    setFirstRowIndex(pageSize * (page - 1));\n  }}\n/>\n```\n\n_Note: The_ `Pagination` _component isn't inherently connected in any way to the_ `DataTable` _- we need to tell it what to do when a change occurs using the_ `onChange` _prop. This includes both page size changes and displaying different rows._\n\n_Note: Like the other Carbon React components,_ `Pagination` _component examples can be found in [Storybook](http://react.carbondesignsystem.com/?selectedKind=Pagination) by browsing the story and knobs._\n\nThat does it! Your data table should fetch GitHub data on first render. You can expand each row to see the repository's description. You can modify the pagination items per page and cycle through pages or jump to a specific page of repositories.\n\n## Submit pull request\n\nWe're going to submit a pull request to verify completion of this tutorial step.\n\n### Continuous integration (CI) check\n\nRun the CI check to make sure we're all set to submit a pull request.\n\n```bash\n$ yarn ci-check\n```\n\n_Note: Having issues running the CI check? [Step 1](</tutorial/react/step-1#continuous-integration-(ci)-check>) has troubleshooting notes that may help._\n\n### Git commit and push\n\nBefore we can create a pull request, stage and commit all of your changes:\n\n```bash\n$ git add --all && git commit -m \"feat(tutorial): complete step 3\"\n```\n\nThen, push to your repository:\n\n```bash\n$ git push origin react-step-3\n```\n\n_Note: Having issues pushing your changes? [Step 1](/tutorial/react/step-1#git-commit-and-push) has troubleshooting notes that may help._\n\n### Pull request (PR)\n\nFinally, visit [carbon-tutorial](https://github.com/carbon-design-system/carbon-tutorial) to \"Compare & pull request\". In doing so, make sure that you are comparing to `react-step-3` into `base: react-step-3`.\n\n_Note: Expect your tutorial step PRs to be reviewed by the Carbon team but not merged. We'll close your PR so we can keep the repository's remote branches pristine and ready for the next person!_\n","fileAbsolutePath":"/zeit/3ed0734e/src/pages/tutorial/react/step-3.mdx"}}}}