Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typesafe, Fullstack React & GraphQL with AWS Amplify #211

Closed
swyxio opened this issue Jan 17, 2022 · 0 comments
Closed

Typesafe, Fullstack React & GraphQL with AWS Amplify #211

swyxio opened this issue Jan 17, 2022 · 0 comments

Comments

@swyxio
Copy link
Owner

swyxio commented Jan 17, 2022


source: devto
devToUrl: "https://dev.to/swyx/typesafe-fullstack-react-graphql-with-aws-amplify-b3a"
devToReactions: 33
devToReadingTime: 4
devToPublishedAt: "2020-09-15T21:23:42.704Z"
devToViewsCount: 454
title: Typesafe, Fullstack React & GraphQL with AWS Amplify
published: true
description: This is the blog version of a talk I am giving at React Summit 2020
category: tutorial
tags: React, GraphQL, AWS
slug: aws_typesafe_fullstack_react
canonical_url: https://www.swyx.io/writing/aws_typesafe_fullstack_react
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/1hfx0h8s4cb9lmot9c4m.png

This is the blog form of a talk I gave at React Summit and Reactathon 2020

{% youtube ja6meOLHjIg %}

Resources

I am going to skim over the slides, which are available here.

GitHub Repo for this demo: https://github.com/sw-yx/talk-typesafe-fullstack-react-demo-cms

I will also assume you already have the AWS Amplify CLI setup and configured.

Livecode Demo Script

First we clone our premade React + TypeScript app and initialize it as an AWS Amplify project:

git clone https://github.com/sw-yx/talk-typesafe-fullstack-react-demo-cms
cd talk-typesafe-fullstack-react-demo-cms
yarn
amplify init # select defaults for everything

At this point we have our simple app with some mock data:

https://user-images.githubusercontent.com/6764957/93261590-7c13f980-f7d5-11ea-9fda-b482ac1abdac.png

This gives us a strongly typed frontend with React and TypeScript! If you wish to learn how to wield React and TypeScript well, check out the React and TypeScript cheatsheet I have been maintaining for over two years!

Adding a GraphQL Database

We will now add a strongly typed backend to complement the frontend, using Amplify and AWS AppSync:

amplify add api

# choose the graphql option and defaults for the rest

? Please select from one of the below mentioned services: GraphQL
? Provide API name: myapiname
? Choose the default authorization type for the API API key
? Enter a description for the API key: 
? After how many days from now the API key should expire (1-365): 7
? Do you want to configure advanced settings for the GraphQL API No, I am do
ne.
? Do you have an annotated GraphQL schema? No
? Choose a schema template: Single object with fields (e.g., “Todo” with ID,
 name, description)

The following types do not have '@auth' enabled. Consider using @auth with @model
         - Todo
Learn more about @auth here: https://docs.amplify.aws/cli/graphql-transformer/directives#auth


GraphQL schema compiled successfully.

? Do you want to edit the schema now? Yes

We'll use GraphQL SDL to define our database schema:

# amplify/backend/api/myapiname/schema.graphql
type Blog @model {
  id: ID!
  title: String!
  image: String!
  body: String!
}

That @model there is a special GraphQL directive, which AppSync uses to provision infrastructure for you alongside your GraphQL model via a library called GraphQL Transform. It has loads more goodies you can explore on your own, like @auth, @searchable, @function and @predictions, that you can add to your backend.

Provisioning this infrastructure in AWS takes a long time, so we'll kick it off in the background while we work on the rest of the app:

amplify push -y # skips the yes check

Wiring up Backend to Frontend

We're in the home stretch. We'll need the aws-amplify library for interacting from the frontend:

yarn add -D aws-amplify

Notice that during amplify init an aws-exports.js file was generated in your src folder, with some non-secret information for your backend. We'll use this to wire up our app with AWS Amplify:

// // src/index.tsx

// the other imports
import Amplify from 'aws-amplify';
import awsconfig from './aws-exports';
Amplify.configure(awsconfig);

// rest of the app

You also notice that during amplify push there was an autogenerated folder in src/graphql with a bunch of GraphQL queries. We will use this in our app!

Optional step first - we can configure the codegen to generate typescript, so that types and auto imports work:

amplify codegen configure

? Choose the code generation language target typescript
? Enter the file name pattern of graphql queries, mutations and subscriptions src/
graphql/**/*.ts
? Enter the file name for the generated code src/API.ts
? Enter maximum statement depth [increase from default if your schema is deeply nested] 2

Then we will use the listBlogs query in our app!

// src/App.tsx
import { API } from 'aws-amplify'; // new
import { listBlogs } from "./graphql/queries"; // new
// other imports here

function App() {
  
  // new
  React.useEffect(fetchBlogs);
  function fetchBlogs() {
    const query = API.graphql({ query: listBlogs }) as Promise<any>
    query.then(
      ({
        data: {
          listBlogs: { items },
        },
      }) => setBlogs(items)
    );
  }
  // etc
}

This sets up the blog items to refresh from backend whenever the app rerenders.

Then we'll also do the same for adding and updating blogs:

// make sure to import createBlog and updateBlog

  async function addBlog(values: Blog) {
    const timestamp = new Date();
    const newBlog: Blog = {
      ...values,
      id: uuidv4(),
      createdAt: timestamp,
      updatedAt: timestamp,
    };
    setBlogs([...blogs, newBlog]);
    await API.graphql({query: createBlog, variables: {input: values}}) // NEW!
  }
  function _updateBlog(oldValues: Blog) {
    return async function (newValues: Blog) {
      const timestamp = new Date();
      const newBlog: Blog = {
        ...newValues,
        createdAt: oldValues.createdAt,
        updatedAt: timestamp,
      };
      setBlogs([...blogs.filter((x) => x.id !== oldValues.id), newBlog]);

      const { createdAt, updatedAt, ...input } = newBlog; // NEW!
      await API.graphql({ query: updateBlog, variables: { input } }); // NEW!
    };
  }

And there you have it! The basics of an end to end typed app!

You got stuck you can see the completed version of the app here https://github.com/sw-yx/talk-react-summit-demo-cms/blob/withAWS/src/App.tsx and the slides are here.

Alt Text

I'm sure you have questions - let's hear them!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant