DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
  1. DZone
  2. Data Engineering
  3. Databases
  4. AWS Amplify GraphQL Queries With TypeScript and Hooks

AWS Amplify GraphQL Queries With TypeScript and Hooks

With the advent of hooks, we can create some nice utilities for ourselves that let us leverage the power of TypeScript with our GraphQL queries.

Mat Warger user avatar by
Mat Warger
·
May. 28, 19 · Tutorial
Like (2)
Save
Tweet
Share
9.72K Views

Join the DZone community and get the full member experience.

Join For Free

I'm a big fan of AWS Amplify. I'm also a big fan of TypeScript.

Amplify is not built with TypeScript, and to use it effectively, sometimes you need to give it a little help, especially when it comes to GraphQL. With the advent of hooks, we can create some nice utilities for ourselves that let us leverage the power of TypeScript with our GraphQL queries. Let's see what that looks like.

I'll be assuming familiarity with React and TypeScript, including the usage of Amplify and GraphQL for this post. There are tons of great resources online. Here's a great set of steps to set up a similar project. Or, you can clone the sample app and run amplify init at the root of the project to see the final result.

Simple Query

From our sample app we have a list of popular games we want to retrieve. The query looks like this:

popularGames {
    id
    name
    popularity
    url
    summary
    # omitted for brevity
}

Starting out, this is a great first start to what we're going for. We want to use useEffect to handle fetching our data. We're using Amplify's graphql method and passing the GraphQL query from above to the graphqlOperation method.

React.useEffect(() => {
  const fetchGames = async () => {
    try {
      const response = await API.graphql(graphqlOperation(popularGames));
    } catch (error) {
      console.log(error);
    }
  };

  fetchGames();
}, []);
The response objects has a data property, which contains our list of games. Here's a couple from the list.

{
  "data": {
    "popularGames": [
      {
        "id": "76882",
        "name": "Sekiro: Shadows Die Twice",
        "popularity": 3954.25
      },
      {
        "id": "114455",
        "name": "Pacify",
        "popularity": 1472.0
      }
    ]
  }
}

We want to display these on our page, so we need to load them into state. With hooks, you accomplish this by creating a useState declaration and then using the method created for you to load them into state.

const [gameData, setGameData] = React.useState(undefined);

React.useEffect(() => {
  const fetchGames = async () => {
    try {
      const response: any = await API.graphql(graphqlOperation(popularGames));
      setGameData(response.data);
    } catch (error) {
      console.log(error);
    }
  };

  fetchGames();
}, []);

At this point, you could display your games on the page using the gameData object.

But in TypeScript land, we actually have more problems here. By initializing the state object to undefined, TypeScript can only infer that the value allowed for the gameData object is undefined, and will give us an error if we try to set our query response using the setGameData method. Additionally, there is a keyword we have used to get past this problem that bites many a first-time TypeScript developer in the ass.

any

This word will strike fear into the hearts of all who witness it. At least, it should if you want your future self to thank your past self at some point (Thanks, Paul, for this great insight).

We don't want anys anywhere.

We really want to try our best to give ourselves and our tools as much power as possible.

We can't tell what our data will be right now, which is a problem... but Amplify can help us.

Types to the Rescue

In our project, if it's not configured already, we need to run amplify configure codegen. This will setup code generation and walk us through the process of generating types based on our queries. This is super helpful (and as far as I'm concerned, should be the default if a .tsconfig file is present at the root of the project).

This gives us a type that we can use for our data. Normally, we could just throw this after the variable and be done with it.

const response: { data: PopularGamesQuery } = await API.graphql(
  graphqlOperation(popularGames)
);

We know that response is going to be this type if the operation doesn't fail. However, the types returned by the graphql function are a mashup of GraphQLResult and Observable since this same function is used for both. Until this changes, we're going to let it know what we expect to get back. We can do this by using the as keyword to tell TypeScript what we know our type will be.

const response = (await API.graphql(graphqlOperation(popularGames))) as {
  data: PopularGamesQuery;
};

Now we get the type help that we want. Hovering over the response object confirms that TypeScript recognizes the response to be an object with a data property of type PopularGamesQuery.

Games, setState

We'll use the same type to tell our useState function how we want to utilize our gameData object.

useState accepts a generic type parameter that allows us to inform the function about the type we want to use.

const [gameData, setGameData] = React.useState<PopularGamesQuery | undefined>(
  undefined
);

Here, we have passed the same PopularGamesQuery type (as well as the possible undefined value we use to initialize it with). This consoles the TypeScript compiler and we can move forward with displaying our games.

As simple as this is, there are a few boilerplate-y things that are staring us in the face. We can extract these things out and create some re-usable code that will make future queries in other components much easier to set up. Custom hooks to the rescue!

Stay tuned for the next post where we do just that!

TypeScript AWS Database GraphQL Hook

Published at DZone with permission of Mat Warger, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Using GPT-3 in Our Applications
  • Choosing the Right Framework for Your Project
  • Understanding and Solving the AWS Lambda Cold Start Problem
  • 3 Main Pillars in ReactJS

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: