Build Your First App with React's Context API

Build Your First App with React's Context API

Build Your First App with React's Context API. One of React's latest features is the Context API. Up until now, Context within React has been somewhat experimental, but still used in quite a few popular libraries, like Redux and React Router.

Build Your First App with React's Context API. One of React's latest features is the Context API. Up until now, Context within React has been somewhat experimental, but still used in quite a few popular libraries, like Redux and React Router.

One of React’s latest features is the Context API. Up until now, Context within React has been somewhat experimental, but still used in quite a few popular libraries, like Redux and React Router. There are plenty of ways to avoid using Context, but sometimes it can be really useful.

One really good use case for Context is keeping track of authentication. In fact, React’s official documentation for the Context API mentions it can be used for authentication.

Context is designed to share data that can be considered “global” for a tree of React components, such as the current authenticated user, theme, or preferred language.### Table of Contents

The examples in their documentation are helpful, but they don’t actually include an example of sharing the authenticated user. I’ll show you here how one way to use the new Context API to simply keep track of whether a user is authenticated, and some basic profile information.

React Context in a Nutshell

Before going too far down the rabbit hole, let me give you a quick introduction into the Context API. As of React version 16, React ships with a function called createContext that takes a single value parameter. Calling createContext gives you both a Provider and Consumer component.

You can render the Provider component anywhere in your app - in multiple places if you like. If there is a Consumer anywhere inside the Provider (even deeply nested somewhere), it will have access to that value parameter in the form of a render function as a child. Each Provider can also override the value. For example:

import { createContext } from 'react';

const { Provider, Consumer } = createContext('default value');

export default () =>
  <main>
    <Provider>
      <Consumer>{value => <span>{value}</span>}</Consumer>
    </Provider>
    <Provider value="overridden value">
      <div>
        <Consumer>{value => <span>{value}</span>}</Consumer>
      </div>
    </Provider>
  </main>
);

Will render the following:

<main>
  <span>default value</span>
  </div>
    <span>overridden value</span>
  </div>
</main>

Because Provider is just a component, you can easily create a wrapper component that passes its state into the value prop of the Provider. Then you will have access to that component’s state anywhere in the app via the Consumer. In this tutorial, I’ll show you how to use one component to keep track of auth state changes and pass that information down via the Context API.

Build a Simple React App

The quickest way to get started with React in my experience is using the official Create React App CLI. It bootstraps an app for you giving you some decent defaults. To use it, install it globally with NPM, then run it with the name of your app as a parameter. This will create a new folder with everything you need to get started, and will even install the dependencies for you. You can then run the app using yarn start.

npm install --global [email protected] [email protected]
create-react-app react-context
cd react-context
yarn start

You should now be able to see your app running by visiting [http://localhost:3000](http://localhost:3000 "http://localhost:3000") with your browser.

For this tutorial, I’ll show you how you can take advantage of the new Context API to cut down some of the boilerplate that is often paired with authentication. Before getting started with Context, you’ll need to set up authentication in order to tie it in.

Create an Okta Application

One simple way to add authentication to your project is with Okta. Okta is a cloud service that allows developers to create, edit, and securely store user accounts and user account data, and connect them with one or multiple applications. Our API enables you to:

If you don’t already have one, sign up for a forever-free developer account. Log in to your developer console, navigate to Applications, then click Add Application. Select Single-Page App, then click Next.

Since Create React App runs on port 3000 by default, you should add that as a Base URI and Login Redirect URI. Your settings should look like the following:

Click Done to save your app, then copy your Client ID and paste it as a variable into a file called .env.local in the root of your project. This will allow you to access the file in your code without needing to store credentials in source control. You’ll also need to add your organization URL (without the -admin suffix). Environment variables (other than NODE_ENV) need to start with REACT_APP_ in order for Create React App to read them, so the file should end up looking like this:

.env.local

REACT_APP_OKTA_CLIENT_ID={yourClientId}
REACT_APP_OKTA_ORG_URL=https://{yourOktaDomain}

The easiest way to add authentication with Okta is to use Okta’s React SDK. You’ll also need to add routes, which can be done using React Router. I’ll also have you start adding icons to the app (for now as an avatar icon to show you’re logged in).

yarn add @okta/[email protected] [email protected]

For routes to work properly using React Router, you need to wrap your whole application in a router (for the web, you need to use BrowserRouter). Similarly, to allow access to authentication anywhere in the app, you need to wrap the app in a Security component provided by Okta. Okta also needs access to the router, so the Security component should be nested inside the router. You should modify your src/index.js file to look like the following:

src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { Security } from '@okta/okta-react';

import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';

const oktaConfig = {
  issuer: `${process.env.REACT_APP_OKTA_ORG_URL}/oauth2/default`,
  redirect_uri: `${window.location.origin}/implicit/callback`,
  client_id: process.env.REACT_APP_OKTA_CLIENT_ID,
};

ReactDOM.render(
  <BrowserRouter>
    <Security {...oktaConfig}>
      <App />
    </Security>
  </BrowserRouter>,
  document.getElementById('root'),
);

registerServiceWorker();

Now in src/App.js you can use Routes that tell the app to only render a certain component if the current URL matches the given path. You can also use Links to create a link to that route (or page) and properly modify the browser’s history to work in a single-page app.

Go ahead and create a nav tag with links to the Home page (/) and a Profile page (/profile). Also, create a main tag containing your routes. For now just stub in some inline components that render the name of the page.

By using Okta’s SecureRoute you will find that whenever you try to go to that page you will need to be logged in. If you’re not currently logged in, you’ll be redirected to /implicit/callback to log in. In order for that route to actually log you in, you also need to create a route that renders Okta’s ImplicitCallback component.

src/App.js

--- a/src/App.js
+++ b/src/App.js
@@ -1,4 +1,7 @@
 import React, { Component } from 'react';
+import { Link, Route } from 'react-router-dom';
+import { SecureRoute, ImplicitCallback } from '@okta/okta-react';
+
 import logo from './logo.svg';
 import './App.css';

@@ -9,10 +12,16 @@ class App extends Component {
         <header className="App-header">
           <img src={logo} className="App-logo" alt="logo" />
           <h1 className="App-title">Welcome to React</h1>
+          <nav className="App-nav">
+            <Link to="/">Home</Link>
+            <Link to="/profile">Profile</Link>
+          </nav>
         </header>
-        <p className="App-intro">
-          To get started, edit <code>src/App.js</code> and save to reload.
-        </p>
+        <main className="App-intro">
+          <Route exact path="/" component={() => 'Home Page'} />
+          <SecureRoute exact path="/profile" component={() => 'Profile page'} />
+          <Route path="/implicit/callback" component={ImplicitCallback} />
+        </main>
       </div>
     );
   }

Note: You can apply a diff in git by copying it to a file and using the git apply command. If you’re following along this avoids having to write the file out manually. For example, if you save the above as a file named app.diff, then from your project folder, you could type git apply app.diff and it should apply those changes.

To make this look a little nicer, add a bit of CSS to let the header expand to the content, give the main part of the app some padding, and make the nav links a bit more readable.

src/App.css

--- a/src/App.css
+++ b/src/App.css
@@ -9,17 +9,35 @@

 .App-header {
   background-color: #222;
-  height: 150px;
+  min-height: 150px;
   padding: 20px;
   color: white;
 }

+.App-nav {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.App-nav a {
+  color: white;
+  padding: 0 5px;
+  text-decoration: none;
+  cursor: pointer;
+}
+
+.App-nav a:hover {
+  text-decoration: underline;
+}
+
 .App-title {
   font-size: 1.5em;
 }

 .App-intro {
   font-size: large;
+  margin: 1em;
 }

You should now have a slightly modified version of the default page from Create React App that says “Home page”. You should also now be able to click on the Profile link and you will be prompted to log in to your account. Upon success, you’ll be taken to the profile page, that at the moment just says Profile page.

Note: You may need to restart the development server after adding the environment variables. You can do this by going to the terminal running the server and hitting ctrl-c, then re-running the yarn start command.

Add a User Greeting with React Context

Using React’s new Context API, you can create a component that you will use to wrap your entire application, similar to the way BrowserRouter or Security works. Once that Provider is in place, you can access pieces of authentication anywhere in the application without a lot of boilerplate.

In this case, create a context using createContext. You’ll then check when the component is first mounted, and again whenever it updates, if the user is authenticated. If this is different from the current state, then it also checks for the user and saves that as well. The reason the state is only updated whenever the authentication is different from the previous state is that otherwise, the componentDidUpdate function would trigger another update, sending this component into an infinite render loop.

To keep this simple to use, the default export is the Context’s Consumer. The Provider component is exported separately and is wrapped with Okta’s withAuth to give it access to the auth prop.

Note: Checking authentication during componentDidUpdate is admittedly not the most efficient method. At the time of this writing, there is not a simple way to detect when the state of authorization changes, so this is a simple approach for demo purposes. This example might not work well for larger applications.

src/Auth.js

import React, { createContext, Component } from 'react';
import { withAuth } from '@okta/okta-react';

const AuthContext = createContext({
  user: null,
  isAuthenticated: null,
});

export default AuthContext.Consumer;

class AuthController extends Component {
  state = {
    user: null,
    isAuthenticated: null,
  }

  componentDidUpdate() {
    this.checkAuthentication();
  }

  componentDidMount() {
    this.checkAuthentication();
  }

  async checkAuthentication() {
    const isAuthenticated = await this.props.auth.isAuthenticated();
    if (isAuthenticated !== this.state.isAuthenticated) {
      const user = await this.props.auth.getUser();
      this.setState({ isAuthenticated, user });
    }
  }

  render() {
    return (
      <AuthContext.Provider value={this.state}>
        {this.props.children}
      </AuthContext.Provider>
    );
  }
}

export const AuthProvider = withAuth(AuthController);

The app’s main entry point now needs to be wrapped in the AuthProvider. It needs to be inside Security so that it can access the auth using withAuth.

src/index.js

--- a/src/index.js
+++ b/src/index.js
@@ -6,6 +6,7 @@ import { Security } from '@okta/okta-react';
 import './index.css';
 import App from './App';
 import registerServiceWorker from './registerServiceWorker';
+import { AuthProvider } from './Auth';

 const oktaConfig = {
   issuer: `${process.env.REACT_APP_OKTA_ORG_URL}/oauth2/default`,
@@ -16,7 +17,9 @@ const oktaConfig = {
 ReactDOM.render(
   <BrowserRouter>
     <Security {...oktaConfig}>
-      <App />
+      <AuthProvider>
+        <App />
+      </AuthProvider>
     </Security>
   </BrowserRouter>,
   document.getElementById('root')

Now that the Context Provider is set up and ready to go, you can start using the Consumer. For a quick example, try changing the homepage to greet the user when they’re logged in. If they aren’t logged in, keep the old message of Welcome to React.

React Contexts take a render function as its child element. The parameters passed in are going to be the state of the provider (the data passed into value). Because of this, to access the user, you need to pass in a function that expects an object containing the key user. If this is null then authentication is still loading. If it’s undefined then the user is not authenticated. Otherwise, it will contain the user’s basic profile information. Go ahead and ignore the loading state for now, and only greet the user once you have their information.

src/App.js

--- a/src/App.js
+++ b/src/App.js
@@ -5,13 +5,21 @@ import { SecureRoute, ImplicitCallback } from '@okta/okta-react';
 import logo from './logo.svg';
 import './App.css';

+import Auth from './Auth';
+
+const welcomeUser = ({ user }) => user
+  ? `Welcome, ${user.given_name || user.name}!`
+  : 'Welcome to React';
+
 class App extends Component {
   render() {
     return (
       <div className="App">
         <header className="App-header">
           <img src={logo} className="App-logo" alt="logo" />
-          <h1 className="App-title">Welcome to React</h1>
+          <h1 className="App-title">
+            <Auth>{welcomeUser}</Auth>
+          </h1>
           <nav className="App-nav">
             <Link to="/">Home</Link>
             <Link to="/profile">Profile</Link>

Create a Login/Logout Link

A pretty common scenario with authentication is having a button or link that you can click to log you in when you’re authenticated. You can use the same React Context to determine whether or not a user is logged in.

In order to properly log the user in or out when they click the link, you can wrap the component with withAuth to get access to the login and logout functions of auth.

This time, you don’t want the user to click either Login or Logout if you’re not sure what the state of authentication is yet. You could implement some sort of loading icon here, but for this demo just render nothing until you know whether or not the user is logged in.

src/LoginButton.js

import React from 'react';
import { withAuth } from '@okta/okta-react';

import Auth from './Auth';

export default withAuth(({ auth }) => (
  <Auth>
    {({ isAuthenticated }) => {
      if (isAuthenticated === null) return null;

      return (
        <a onClick={() => isAuthenticated ? auth.logout() : auth.login()}>
          {isAuthenticated ? 'Logout' : 'Login'}
        </a>
      );
    }}
  </Auth>
));

Now you can add the Login/Logout link to your list of nav items:

src/App.js

--- a/src/App.js
+++ b/src/App.js
@@ -6,6 +6,7 @@ import logo from './logo.svg';
 import './App.css';

 import Auth from './Auth';
+import LoginButton from './LoginButton';

 const welcomeUser = ({ user }) => user
   ? `Welcome, ${user.given_name || user.name}!`
@@ -23,6 +24,7 @@ class App extends Component {
           <nav className="App-nav">
             <Link to="/">Home</Link>
             <Link to="/profile">Profile</Link>
+            <LoginButton />
           </nav>
         </header>
         <main className="App-intro">

Create a Real Profile Page

From the user value in your Context, you can also now get access to the user’s basic profile information.

Semantically, a dl HTML tag is a “Description List” element. This is a good, basic way to display metadata. However, you’ll probably want to add a little bit of simple styling. This will make sure the text isn’t center-aligned, and make the term (the dt tag) bold. Create a new file Profile.css that you’ll import in your profile page.

src/Profile.css

dl {
  text-align: left;
}

dt {
  padding: 4px 0;
  font-weight: bold;
}

Lodash provides a suite of utilities to manipulate data. To keep things simple and automated, try using that to convert the name of a key to something more personable. The startCase function will convert a string like given_name to Given Name. To add Lodash as a dependency, run the following:

yarn add [email protected]

The updated_at key is actually just a number representing the number of seconds from 1970, so you can convert that to a human-readable string in JavaScript using new Date(updated_at * 1000).toString().

Putting all that together, you can create a functional component that takes a user prop, and wrap that in the Auth Context Consumer. This time, show a simple loading message if the user isn’t loaded yet. Technically, the user will be undefined if authentication finished and there is no user, but because this is in a SecureRoute, if there is no user then the page will redirect to the home page.

src/Profile.js

import React, { Fragment } from 'react';
import { startCase } from 'lodash';

import Auth from './Auth';
import './Profile.css';

const ProfilePage = ({ user }) => {
  if (!user) return 'Loading...';

  return (
    <dl>
      {Object.keys(user).sort().map(key => (
        <Fragment key={key}>
          <dt>{startCase(key)}</dt>
          <dd>{key === 'updated_at' ? new Date(user[key] * 1000).toString() : user[key]}</dd>
        </Fragment>
      ))}
    </dl>
  );
}

export default () => <Auth>{ProfilePage}</Auth>;

In your app’s routes, replace the mock profile page with a reference to the real one you just created:

--- a/src/App.js
+++ b/src/App.js
@@ -7,6 +7,7 @@ import './App.css';

 import Auth from './Auth';
 import LoginButton from './LoginButton';
+import ProfilePage from './Profile';

 const welcomeUser = ({ user }) => user
   ? `Welcome, ${user.given_name || user.name}!`
@@ -29,7 +30,7 @@ class App extends Component {
         </header>
         <main className="App-intro">
           <Route exact path="/" component={() => 'Home Page'} />
-          <SecureRoute exact path="/profile" component={() => 'Profile page'} />
+          <SecureRoute exact path="/profile" component={ProfilePage} />
           <Route path="/implicit/callback" component={ImplicitCallback} />
         </main>
       </div>

Now when you go to the profile page, you get some details about the logged in user.

Learn More

React Tutorial: Building and Securing Your First App

Simple User Authentication in React

React Router: Add the Power of Navigation

Learn React - React Crash Course 2019 - React Tutorial with Examples

React Hooks Tutorial for Beginners: Getting Started With React Hooks

Learn React.js for Beginners

React - The Complete Guide (incl Hooks, React Router, Redux)

Modern React with Redux [2019 Update]

React Native - The Practical Guide

MERN Stack Front To Back: Full Stack React, Redux & Node.js

Full-Stack Web Apps with Meteor and React

React Hooks

React and APIs - Full Tutorial - Hacker News API Application

React and APIs - Full Tutorial - Hacker News API Application

Learn how to use APIs with React in this intermediate tutorial. We're going to be creating a small application in React that calls the Hacker News API. We'll be looking at React memo, Axios (to make API calls), styled components, and finally we will test our work using React Testing Library.

React and APIs - Full Tutorial - Hacker News API Application

Once we have done all this we will run our application through Lighthouse (a browser extension) that allows us to test for accessibility, performance and so much more. We will be making 500+ automated API calls in this application, and I want to show you how to use memo with React so that we can avoid making multiple network calls if we already have the data.

💻 Code: https://github.com/karlhadwen/newsreader

⭐️ Course Contents ⭐️
⌨️ (0:00:00) Introduction (what are we building?), tech stack talk
⌨️ (0:01:50) Using create-react-app as our base
⌨️ (0:03:30) Stripping out the files & content that we do not need
⌨️ (0:05:00) Refactoring to named exports
⌨️ (0:08:35) Modifying our .env file
⌨️ (0:09:15) Scaffolding our application
⌨️ (0:10:15) Looking at the Hacker News Api
⌨️ (0:11:50) Looking at all the news article Ids
⌨️ (0:12:58) Adding Axios using Yarn
⌨️ (0:13:00) Creating our hnApi.js service file
⌨️ (0:15:07) Adding the ability to get all story Ids from HN Api
⌨️ (0:17:14) Starting work on App.js
⌨️ (0:22:30) Adding useEffect to App.js to show all story Ids
⌨️ (0:30:00) Explaining how useEffect works
⌨️ (0:36:00) Creating our StoriesContainer.js container/component
⌨️ (0:37:50) Adding the ability to get stories from HN Api
⌨️ (0:39:50) Demonstrating the results that we receive from the HN Api
⌨️ (0:41:30) Creating our Story.js component file
⌨️ (0:43:15) Adding our Story component to the StoriesContainer component
⌨️ (0:44:10) Adding storyId as a prop to the Story.js component
⌨️ (0:46:40) Adding state to our Story.js component
⌨️ (0:47:10) Using useEffect to get a story in our Story.js component
⌨️ (0:47:40) Adding validation when getting stories
⌨️ (0:49:00) Dumping our stories onto the page
⌨️ (0:49:55) Building out the Story.js component with real data
⌨️ (0:53:20) Adding a selector for the story fields
⌨️ (0:56:00) Adding styled components
⌨️ (0:57:00) Building out our StoryStyles.js file using styled components
⌨️ (0:59:00) Adding a title to StoriesContainer.js
⌨️ (1:00:00) Adding a StoryWrapper to our Story.js component
⌨️ (1:01:50) More work on styling
⌨️ (1:02:30) Adding styling for StoryMeta
⌨️ (1:03:55) Adding styling for StoryMetaElements & styled component props
⌨️ (1:04:55) Adding our styled components to our Story.js component
⌨️ (1:11:30) Adding StoriesContainerStyles for more styling on the container
⌨️ (1:12:05) Looking at adding global styles (createGlobalStyle)
⌨️ (1:13:00) Adding our container styles to StoriesContainer.js
⌨️ (1:14:55) Brief look at the React profiler
⌨️ (1:16:00) Quick run through as to what we have built so far
⌨️ (1:18:10) Making our time display properly using mapTime.js
⌨️ (1:22:00) Adding InfiniteScroll to our application (custom hook)
⌨️ (1:22:40) Constants to be used by InfiniteScroll for per page items
⌨️ (1:39:05) Adding debounce functionality for scrolling
⌨️ (1:42:00) Adding a fixture folder with fixtures for tests
⌨️ (1:46:00) Testing! Lets test App.js
⌨️ (1:48:00) Adding react-testing-library to our application
⌨️ (1:59:00) Adding Jest coverage (good practise to do so)
⌨️ (2:02:00) Testing the StoriesContainer.js
⌨️ (2:03:40) Testing the Story.js component
⌨️ (2:10:00) Testing the HnApi.js file
⌨️ (2:22:18) Looking at our coverage and more testing!
⌨️ (2:22:53) Collecting coverage from the right places
⌨️ (2:25:43) Looking at React memo
⌨️ (2:27:33) Adding memo to Story.js to prevent additional Api calls
⌨️ (2:29:18) Overview of what we have achieved!
⌨️ (2:30:29) Running our application through Lighthouse!
⌨️ (2:33:00) Thanks for watching, I hope you learned a lot!

How to CRUD Operations using Reactjs and ASP.NET Web API

How to CRUD Operations using Reactjs and ASP.NET Web API

In this article, I'm going to perform CRUD operations using React.js, ASP.NET Web API and SQL Server. ReactJS is an open-source JavaScript library that is used for creating user interfaces. It is developed and maintained by Facebook.

Introduction

In this article, I'm going to perform CRUD operations using  React.js and ASP.NET Web API. Reactjs is an open-source JavaScript library that is used for creating user interfaces. It is developed and maintained by Facebook. Learn more about React here.

Prerequisites

  • We should have the basic knowledge of React.js and Web API.
  • Visual Studio and Visual Studio Code IDE should be installed on your system.
  • SQL Server Management Studio.

Technologies we will use:

  • ASP.NET Web API.
  • ReactJS
  • SQL Server.
  • React strap.
  • Bootstrap

You may also like: Angular vs React vs Vue: Which one will be popular in 2020.

Step 1: Create a Table in the Database

Open SQL Server Management Studio, create a database named "CrudDemo," and in this database, create a table. Give that table a name like "studentmaster."

USE [CrudDemo]  
GO  
CREATE TABLE [dbo].[studentmaster](  
    [Id] [int] IDENTITY(1,1) NOT NULL,  
    [Name] [varchar](50) NULL,  
    [RollNo] [varchar](50) NULL,  
    [Class] [varchar](50) NULL,  
    [Address] [varchar](50) NULL,  
 CONSTRAINT [PK_studentmaster] PRIMARY KEY CLUSTERED   
(  
    [Id] ASC  
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]  
) ON [PRIMARY]  

GO  
Create a New Web API Project

Step 2: Create a New Project.

_Creating a new project in VS Code_

Step 3: Change the Name to CrudUsingReact

_Changing project name to CrudUsingReact_

Step 4: Choose the Web API Template

_Selecting Web API template_

Step 5

Right-click the Models folder from Solution Explorer and go to Add >> New Item >> data.

_Adding data_

Step 6

Click on the "ADO.NET Entity Data Model" option and click "Add."

_Adding Entity Data Model_

Step 7

Select EF Designer from the database and click the "Next" button.

_Choosing EF Designer_

Step 8

Add the connection properties and select database name on the next page and click OK.

_Adding connection properties to db_

Step 9

Check the "Table" checkbox. The internal options will be selected by default. Now, click the "Finish" button.

_Finishing project setup_

Step 10

Right-click on Models folder and add two classes — Student and Response. Now, paste the following codes in these classes:

public class Student  
   {  
       public string Name { get; set; }  
       public string Rollno { get; set; }  
       public string Class { get; set; }  
       public string Address { get; set; }  
   }  
public class Response  
   {  
       public string Status { get; set; }  
       public string Message { get; set; }  
   }  

Step 11

Right-click on the Controllers folder and add a new controller. Name it "Student controller" and add the following namespace in the Student controller.

using CrudUsingReact.Models;  

Step 12

Now, add a method to insert and update data into the database.

[Route("AddotrUpdatestudent")]  
       [HttpPost]  
       public object AddotrUpdatestudent(Student st)  
       {  
           try  
           {  
               if (st.Id == 0)  
               {  
                   studentmaster sm = new studentmaster();  
                   sm.Name = st.Name;  
                   sm.RollNo = st.Rollno;  
                   sm.Address = st.Address;  
                   sm.Class = st.Class;  
                   DB.studentmasters.Add(sm);  
                   DB.SaveChanges();  
                   return new Response  
                   {  
                       Status = "Success",  
                       Message = "Data Successfully"  
                   };  
               }  
               else  
               {  
                   var obj = DB.studentmasters.Where(x => x.Id == st.Id).ToList().FirstOrDefault();  
                   if (obj.Id > 0)  
                   {  

                       obj.Name = st.Name;  
                       obj.RollNo = st.Rollno;  
                       obj.Address = st.Address;  
                       obj.Class = st.Class;  
                       DB.SaveChanges();  
                       return new Response  
                       {  
                           Status = "Updated",  
                           Message = "Updated Successfully"  
                       };  
                   }  
               }  
           }  
           catch (Exception ex)  
           {  
               Console.Write(ex.Message);  
           }  
           return new Response  
           {  
               Status = "Error",  
               Message = "Data not insert"  
           };  

       }  

Step 13

Add other methods to delete and fetch data respectively from the database.

[Route("Deletestudent")]  
      [HttpDelete]  
      public object Deletestudent(int id)  
      {  
          var obj = DB.studentmasters.Where(x => x.Id == id).ToList().FirstOrDefault();  
          DB.studentmasters.Remove(obj);  
          DB.SaveChanges();  
          return new Response  
          {  
              Status = "Delete",  
              Message = "Delete Successfuly"  
          };  
      }  

[HttpGet]  
      public object   Studentdetails()  
      {  

              var a = DB.studentmasters.ToList();  
              return a;  
      }  

Complete Student Controller Code

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Net;  
using System.Net.Http;  
using System.Web.Http;  
using CrudUsingReact.Models;  

namespace CrudUsingReact.Controllers  
{  
    [RoutePrefix("Api/Student")]  
    public class studentController : ApiController  
    {  
        CrudDemoEntities DB = new CrudDemoEntities();  
        [Route("AddotrUpdatestudent")]  
        [HttpPost]  
        public object AddotrUpdatestudent(Student st)  
        {  
            try  
            {  
                if (st.Id == 0)  
                {  
                    studentmaster sm = new studentmaster();  
                    sm.Name = st.Name;  
                    sm.RollNo = st.RollNo;  
                    sm.Address = st.Address;  
                    sm.Class = st.Class;  
                    DB.studentmasters.Add(sm);  
                    DB.SaveChanges();  
                    return new Response  
                    {  
                        Status = "Success",  
                        Message = "Data Successfully"  
                    };  
                }  
                else  
                {  
                    var obj = DB.studentmasters.Where(x => x.Id == st.Id).ToList().FirstOrDefault();  
                    if (obj.Id > 0)  
                    {  

                        obj.Name = st.Name;  
                        obj.RollNo = st.RollNo;  
                        obj.Address = st.Address;  
                        obj.Class = st.Class;  
                        DB.SaveChanges();  
                        return new Response  
                        {  
                            Status = "Updated",  
                            Message = "Updated Successfully"  
                        };  
                    }  
                }  
            }  
            catch (Exception ex)  
            {  
                Console.Write(ex.Message);  
            }  
            return new Response  
            {  
                Status = "Error",  
                Message = "Data not insert"  
            };  

        }  
        [Route("Studentdetails")]  
        [HttpGet]  
        public object   Studentdetails()  
        {  

                var a = DB.studentmasters.ToList();  
                return a;  
        }  

        [Route("StudentdetailById")]  
        [HttpGet]  
        public object StudentdetailById(int id)  
        {  
            var obj = DB.studentmasters.Where(x => x.Id == id).ToList().FirstOrDefault();  
            return obj;  
        }  
        [Route("Deletestudent")]  
        [HttpDelete]  
        public object Deletestudent(int id)  
        {  
            var obj = DB.studentmasters.Where(x => x.Id == id).ToList().FirstOrDefault();  
            DB.studentmasters.Remove(obj);  
            DB.SaveChanges();  
            return new Response  
            {  
                Status = "Delete",  
                Message = "Delete Successfuly"  
            };  
        }  
    }  
}  

Step 14

Now, let's enable CORS. Go to Tools, open NuGet Package Manager, search for CORS, and install the "Microsoft.Asp.Net.WebApi.Cors" package. Open Webapiconfig.cs and add the following lines:

EnableCorsAttribute cors = new EnableCorsAttribute("*", "*", "*");    
config.EnableCors(cors);   
Create React.js Project

Step 15

To create a new ReactJS project, open the command prompt, and enter the following command:

npx create-react-app crudwithceactjs  

Open the newly created project in Visual Studio Code and install Reactstrap and Bootstrap by using the following commands:

npm install --save bootstrap  
npm install --save reactstrap react react-dom  

Step 16

Now, go to the "src" folder and add a new folder "Student" and four new components:

  1. Addstudent.js
  2. Studentlist.js
  3. Editstudent.js
  4. Table.js

_Adding components to the Student folder_

Step 17

Install the Axios library by using the following command. Learn more about Axios library

npm install --save axios  

Step 18

Add routing: Use the following command to add routing in React.

npm install react-router-dom --save    

Step 19

Now, open the Addstudent.js file and add the following code:

import React from 'react';  
import axios from 'axios';  
import '../Student/Addstudent.css'  
import { Container, Col, Form, Row, FormGroup, Label, Input, Button } from 'reactstrap';  
class Addstudent extends React.Component{  
constructor(props){  
super(props)  
this.state = {  
Name:'',  
RollNo:'',  
Class:'',  
Address:''  
}  
}   
Addstudent=()=>{  
  axios.post('http://localhost:52564/Api/Student/AddotrUpdatestudent/', {Name:this.state.Name,RollNo:this.state.RollNo,  
  Class:this.state.Class, Address:this.state.Address})  
.then(json => {  
if(json.data.Status==='Success'){  
  console.log(json.data.Status);  
  alert("Data Save Successfully");  
this.props.history.push('/Studentlist')  
}  
else{  
alert('Data not Saved');  
debugger;  
this.props.history.push('/Studentlist')  
}  
})  
}  

handleChange= (e)=> {  
this.setState({[e.target.name]:e.target.value});  
}  

render() {  
return (  
   <Container className="App">  
    <h4 className="PageHeading">Enter Student Informations</h4>  
    <Form className="form">  
      <Col>  
        <FormGroup row>  
          <Label for="name" sm={2}>Name</Label>  
          <Col sm={10}>  
            <Input type="text" name="Name" onChange={this.handleChange} value={this.state.Name} placeholder="Enter Name" />  
          </Col>  
        </FormGroup>  
        <FormGroup row>  
          <Label for="address" sm={2}>RollNo</Label>  
          <Col sm={10}>  
            <Input type="text" name="RollNo" onChange={this.handleChange} value={this.state.RollNo} placeholder="Enter RollNo" />  
          </Col>  
        </FormGroup>  
        <FormGroup row>  
          <Label for="Password" sm={2}>Class</Label>  
          <Col sm={10}>  
            <Input type="text" name="Class" onChange={this.handleChange} value={this.state.Class} placeholder="Enter Class" />  
          </Col>  
        </FormGroup>  
        <FormGroup row>  
          <Label for="Password" sm={2}>Address</Label>  
          <Col sm={10}>  
            <Input type="text" name="Address" onChange={this.handleChange} value={this.state.Address} placeholder="Enter Address" />  
          </Col>  
        </FormGroup>  
      </Col>  
      <Col>  
        <FormGroup row>  
          <Col sm={5}>  
          </Col>  
          <Col sm={1}>  
          <button type="button" onClick={this.Addstudent} className="btn btn-success">Submit</button>  
          </Col>  
          <Col sm={1}>  
            <Button color="danger">Cancel</Button>{' '}  
          </Col>  
          <Col sm={5}>  
          </Col>  
        </FormGroup>  
      </Col>  
    </Form>  
  </Container>  
);  
}  

}  

export default Addstudent;  

Add a new file  Addstudet.css file and add the following CSS classes. Import this file in the  Addstudent.js component.

.PageHeading    
{    
  margin-top: 10px;    
  margin-bottom: 10px;    
  color :black !important;    
}    

Step 20

Now, add a Table.js file and add the following code:

import React, { Component } from 'react';  
import axios from 'axios';  
import { Link } from 'react-router-dom';  
class Table extends Component {  
  constructor(props) {  
    super(props);  
    }  

    DeleteStudent= () =>{  
     axios.delete('http://localhost:52564/Api/Student/Deletestudent?id='+this.props.obj.Id)  
    .then(json => {  
    if(json.data.Status==='Delete'){  
    alert('Record deleted successfully!!');  
    }  
    })  
    }  
  render() {  
    return (  
        <tr>  
          <td>  
            {this.props.obj.Name}  
          </td>  
          <td>  
            {this.props.obj.RollNo}  
          </td>  
          <td>  
            {this.props.obj.Class}  
          </td>  
          <td>  
            {this.props.obj.Address}  
          </td>  
          <td>  
          <Link to={"/edit/"+this.props.obj.Id} className="btn btn-success">Edit</Link>  
          </td>  
          <td>  
            <button type="button" onClick={this.DeleteStudent} className="btn btn-danger">Delete</button>  
          </td>  
        </tr>  
    );  
  }  
}  

export default Table;  

Step 21

Now, add a studentlist.js file and add the following code.

import React, { Component } from 'react';  
import axios from 'axios';  
import Table from './Table';  

export default class Studentlist extends Component {  

  constructor(props) {  
      super(props);  
      this.state = {business: []};  
    }  
    componentDidMount(){  
      debugger;  
      axios.get('http://localhost:52564/Api/Student/Studentdetails')  
        .then(response => {  
          this.setState({ business: response.data });  
          debugger;  

        })  
        .catch(function (error) {  
          console.log(error);  
        })  
    }  

    tabRow(){  
      return this.state.business.map(function(object, i){  
          return <Table obj={object} key={i} />;  
      });  
    }  

    render() {  
      return (  
        <div>  
          <h4 align="center">Student List</h4>  
          <table className="table table-striped" style={{ marginTop: 10 }}>  
            <thead>  
              <tr>  
                <th>Name</th>  
                <th>RollNo</th>  
                <th>Class</th>  
                <th>Address</th>  
                <th colSpan="4">Action</th>  
              </tr>  
            </thead>  
            <tbody>  
             { this.tabRow() }   
            </tbody>  
          </table>  
        </div>  
      );  
    }  
  }  

Step 22

Add EditStudent.js file with the following code:

import React from 'react';   
import { Container, Col, Form, Row, FormGroup, Label, Input, Button } from 'reactstrap';  
import axios from 'axios'  
import '../Student/Addstudent.css'  
class Edit extends React.Component {  
    constructor(props) {  
        super(props)  

    this.onChangeName = this.onChangeName.bind(this);  
    this.onChangeRollNo = this.onChangeRollNo.bind(this);  
    this.onChangeClass = this.onChangeClass.bind(this);  
    this.onChangeAddress = this.onChangeAddress.bind(this);  
    this.onSubmit = this.onSubmit.bind(this);  

         this.state = {  
            Name: '',  
            RollNo: '',  
            Class: '',  
            Address: ''  

        }  
    }  

  componentDidMount() {  
      axios.get('http://localhost:52564/Api/Student/StudentdetailById?id='+this.props.match.params.id)  
          .then(response => {  
              this.setState({   
                Name: response.data.Name,   
                RollNo: response.data.RollNo,  
                Class: response.data.Class,  
                Address: response.data.Address });  

          })  
          .catch(function (error) {  
              console.log(error);  
          })  
    }  

  onChangeName(e) {  
    this.setState({  
        Name: e.target.value  
    });  
  }  
  onChangeRollNo(e) {  
    this.setState({  
        RollNo: e.target.value  
    });    
  }  
  onChangeClass(e) {  
    this.setState({  
        Class: e.target.value  
    });  
}  
    onChangeAddress(e) {  
        this.setState({  
            Address: e.target.value  
        });  
  }  

  onSubmit(e) {  
    debugger;  
    e.preventDefault();  
    const obj = {  
        Id:this.props.match.params.id,  
      Name: this.state.Name,  
      RollNo: this.state.RollNo,  
      Class: this.state.Class,  
      Address: this.state.Address  

    };  
    axios.post('http://localhost:52564/Api/Student/AddotrUpdatestudent/', obj)  
        .then(res => console.log(res.data));  
        debugger;  
        this.props.history.push('/Studentlist')  
  }  
    render() {  
        return (  
            <Container className="App">  

             <h4 className="PageHeading">Update Student Informations</h4>  
                <Form className="form" onSubmit={this.onSubmit}>  
                    <Col>  
                        <FormGroup row>  
                            <Label for="name" sm={2}>Name</Label>  
                            <Col sm={10}>  
                                <Input type="text" name="Name" value={this.state.Name} onChange={this.onChangeName}  
                                placeholder="Enter Name" />  
                            </Col>  
                        </FormGroup>  
                        <FormGroup row>  
                            <Label for="Password" sm={2}>RollNo</Label>  
                            <Col sm={10}>  
                                <Input type="text" name="RollNo" value={this.state.RollNo} onChange={this.onChangeRollNo} placeholder="Enter RollNo" />  
                            </Col>  
                        </FormGroup>  
                         <FormGroup row>  
                            <Label for="Password" sm={2}>Class</Label>  
                            <Col sm={10}>  
                                <Input type="text" name="Class" value={this.state.Class} onChange={this.onChangeClass} placeholder="Enter Class" />  
                            </Col>  
                        </FormGroup>  
                         <FormGroup row>  
                            <Label for="Password" sm={2}>Address</Label>  
                            <Col sm={10}>  
                                <Input type="text" name="Address"value={this.state.Address} onChange={this.onChangeAddress} placeholder="Enter Address" />  
                            </Col>  
                        </FormGroup>   
                    </Col>  
                    <Col>  
                        <FormGroup row>  
                            <Col sm={5}>  
                            </Col>  
                            <Col sm={1}>  
                          <Button type="submit" color="success">Submit</Button>{' '}  
                            </Col>  
                            <Col sm={1}>  
                                <Button color="danger">Cancel</Button>{' '}  
                            </Col>  
                            <Col sm={5}>  
                            </Col>  
                        </FormGroup>  
                    </Col>  
                </Form>  
            </Container>  
        );  
    }  

}  

export default Edit;  

Step 23

Open the App.js file with the following code in it.

import React from 'react';  
import Addstudent from './Student/Addstudent';  
import Studentlist from './Student/Studentlist';  
import EditStudent from './Student/EditStudent';  
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom';  
import './App.css';  
function App() {  
  return (  
    <Router>  
      <div className="container">  
        <nav className="navbar navbar-expand-lg navheader">  
          <div className="collapse navbar-collapse" >  
            <ul className="navbar-nav mr-auto">  
              <li className="nav-item">  
                <Link to={'/Addstudent'} className="nav-link">Addstudent</Link>  
              </li>  
              <li className="nav-item">  
                <Link to={'/Studentlist'} className="nav-link">Student List</Link>  
              </li>  
            </ul>  
          </div>  
        </nav> <br />  
        <Switch>  
          <Route exact path='/Addstudent' component={Addstudent} />  
          <Route path='/edit/:id' component={EditStudent} />  
          <Route path='/Studentlist' component={Studentlist} />  
        </Switch>  
      </div>  
    </Router>  
  );  
}  

export default App;  

Add the following CSS classes in the App.css file.

.App {    
  text-align: center;    
}    
.navheader{    
  margin-top: 10px;    
  color :black !important;    
  background-color: #b3beca!important    
}    

Now, run the application by using the  npm start command and check the result.

Click on the Add Student button to add a new record into the database.

Click on the Edit button to update a record.

Click on the Delete button to delete a record.

Summary

In this article, we learned how to perform CRUD operations using React, Asp.net Web API, and SQL Server.

Thank for reading. Please share if you liked it!

GraphQL API with AWS and Use with React

GraphQL API with AWS and Use with React

Create a serverless GraphQL API with AWS and consume it with React.

GraphQL has become a go-to API implementation for developers looking to take advantage of features liketype safety, network efficiency, real-time data with subscriptions & more.

Building, managing, & deploying your own GraphQL server can be tedious & time consuming, especially for developers new to the technology that may want to quickly get a real-world, secure & scalable GraphQL API up and running without having to learn how to create it from scratch (as well as spend the time learning best practices around API design & authorization).

Introducing AWS AppSync

Table of Contents

In this post we’ll learn how to use AWS AppSync, a fully managed GraphQL service, to create a serverless GraphQL API. AWS AppSync allows developers to quickly create serverless, scalable & secure GraphQL APIs.

We’ll go through:

Our CLI Tool: AWS Amplify

We’ll be using AWS Amplify to create the AppSync service & connect to it from our React application. AWS Amplify is a CLI & Client toolchain that allows developers to create AWS services from their front-end environment & connect to them from the client-side applications.

The app that we will be building is a restaurant tracker app that will allow us to keep up with all of the restaurants we would like to visit as well as store information about each restaurant. We’ll use React as the front-end for the application.

Getting Started

The AWS Amplify CLI is the tool that we will be using to create the AWS AppSync API. This CLI allows us to create & deploy AWS services directly from the command line. The services that we will be creating are AWS AppSync for the API layer & Amazon Cognito for the authentication provider.

App Features

Users will be able to sign up for an account, sign in to the account, create a restaurant, & query for only the restaurants that the user created.

Creating the React App

First, we’ll create the React application that we’ll be using to connect to our API. To do so, we’ll use Create React App:

create-react-app restaurant-app

# or
npx create-react-app restaurant-app

Once the app is created, we’ll change into the new directory & install aws-amplify:

cd restaurant-app
npm install aws-amplify

Amplify CLI

The next thing we need to do is install & configure the AWS Amplify CLI. To do so, we’ll use npm:

npm install -g @aws-amplify/cli

Once the CLI is installed, we’ll need to configure it to use an IAM user from our AWS account

amplify configure

If you’d like a video walkthrough of how to install & configure the AWS Amplify CLI, click here. Now that the CLI is installed & configured, we can initialize a new Amplify project in our React application. From the inside your React application, run the following command:

amplify init

If you’d like a video walkthrough of how to install & configure the AWS Amplify CLI, click here. Now that the CLI is installed & configured, we can initialize a new Amplify project in our React application. From the inside your React application, run the following command:
Once the project has been initialized, we can go ahead and add an an API & authentication to our app. To do so, we’ll first add authentication.

Adding the AWS AppSync API

To add the AWS AppSync api, we can run the following command:

amplify add api

Now, you’ll be prompted for the following:

Update the schema to this & save the file:

type Restaurant @model {
  id: ID!
  name: String!
  description: String
}

Next, we’ll run the push command to create the services in our account:

amplify push

Now, you’ll be prompted for the following:

Once the push is complete, the AWS AppSync service have been successfully created in our account.

What exactly has been created? If you notice, in the above schema definition, we have an @model directive on the schema type definition. This is part of the Amplify GraphQL Transform library.

The library will recognize this directive & automcatically expand the schema into additional schema that is typically necessary for a robust API, including queries, mutations, subscriptions, resolvers & a data source (Amazon DynamoDB). Everything you need to get up & running is now set up for you using this directive.

If at any time you would like to view the services that have been created in your Amplify configuration, you can run amplify status.

To view the AWS AppSync console & see the API that was just created, click here. To view the Cognito user pool that was just created, click here.

If you’d like a video walkthrough of how to install & configure the AWS Amplify CLI, click here. Now that the CLI is installed & configured, we can initialize a new Amplify project in our React application. From the inside your React application, run the following command:## Testing the API in the AWS Console

Now that the API has been created, we can go to the AWS AppSync console & begin testing it out! To do so, visit the AWS AppSync console (be sure you are in the correct region), & click on the API name you just created.

In the left hand menu, you will see links for your data source, settings, schema, & queries. Feel free to click around here & explore.

What we’d like to do next though is execute mutations & queries against the API. In the left hand menu, click on Queries & try out the following mutation in the query editor:

mutation create {
  createRestaurant(input: {
    name: "Soi"
    description: "Great Thai in Seattle"
  }) {
    id name d
  }
}

Creating a query in the AWS Console

Create a couple of mutations & then we’ll query for them using the following query:

query list {
  listRestaurants {
    items {
      id
      name
      description
    }
  }
}

This query should return an array of restaurans showing the id, name & description for each item created.

You may be wondering where the ID comes from, since all we did was pass in a name & description. The ids are automatically generated by the service (in the resolver mapping template) so you don’t have to pass them in. If you’d like to view the mapping template for any resolver, click on Schema in the left menu, look for the resolver you’d like to view in the resolvers panel on the right.

Integration with React

Now that the services are created, we can wire them up with our React application & begin interacting with them.

The first thing we’ll do is configure the application with our Amplify resources. To configure the React application, open index.js & add the following three lines of code:

import Amplify from 'aws-amplify'
import config from './aws-exports'
Amplify.configure(config)

Next, open App.js. Here, we’ll query for the restaurants & display them in our app. To do so, we’ll need to do 5 things:

  1. Import the APIs from AWS Amplify
  2. Import the query definition
  3. Create initial state to hold the restaurants array
  4. Query for the restaurants array from our API & update the state
  5. Display the restaurants array in the React application.

First, we’ll take care of our imports:

import { API, graphqlOperation } from 'aws-amplify'
import { listRestaurants } from './graphql/queries'

Next, in the class definition, we’ll go ahead & create the state & initialize the query in componentDidMount lifecycle method:

state = { restaurants: [] }
async componentDidMount() {
  try {
    const apiData = await API.graphql(graphqlOperation(listRestaurants))
    const restaurants = apiData.data.listRestaurants.items
    this.setState({ restaurants })
  } catch (err) {
    console.log('error: ', err)
  }
}

In componentDidMount we fetch the data from the AppSync API by using the API class, calling API.graphql passing in the graphqlOperation helper & the query definition. We the store the data in the restaurants array after it has returned from the array & reset the state.

Now, the data is stored in the state & we can render it to our screen. Let’s update the render method to show the restaurant data in our UI:

// rest of class omitted
render() {
    return (
      <div className="App">
        {
          this.state.restaurants.map((rest, i) => (
            <div style={styles.item}>
              <p style={styles.name}>{rest.name}</p>
              <p style={styles.description}>{rest.description}</p>
            </div>
          ))
        }
      </div>
    );
  }
}

const styles = {
  item: {
    padding: 10,
    borderBottom: '2px solid #ddd'
  },
  name: { fontSize: 22 },
  description: { color: 'rgba(0, 0, 0, .45)' }
}

If you’d like a video walkthrough of how to install & configure the AWS Amplify CLI, click here. Now that the CLI is installed & configured, we can initialize a new Amplify project in our React application. From the inside your React application, run the following command:
Now, we should be able to run the app & see the queried data rendered to our screen:

npm start

GraphQL Mutations

Now that we know how to query for data, let’s look at how to submit mutations & create new items in our API. To do so, we’ll create a form with an input that will create new items in our API & display them to the screen.

To do so, we’ll need to do 5 things:

  1. Import the APIs from AWS Amplify
  2. Import the query definition
  3. Create initial state to hold the restaurants array
  4. Query for the restaurants array from our API & update the state
  5. Display the restaurants array in the React application.

First, we’ll import the mutation:

import { createRestaurant } from './graphql/mutations'

Next, we’ll update the state to hold the restaurant name & description:

 state = { name: '', description: '', restaurants: [] }

Now, we’ll create the two methods we’ll need to handle user input & call the API to create a restaurant:

onChange = e => {
  this.setState({ [e.target.name]: e.target.value })
}
createRestaurant = async () => {
  const { name, description } = this.state
  if (name === '' || description === '') return
  try {
    const restaurant = { name, description }
    const restaurants = [...this.state.restaurants, restaurant]
    this.setState({ restaurants, name: '', description: '' })
    await API.graphql(graphqlOperation(createRestaurant, {input: restaurant}))
    console.log('restaurant successfully created!')
  } catch (err) {
    console.log('error: ', err)
  }
}

In the createRestaurant method we do 5 things:

  1. Import the APIs from AWS Amplify
  2. Import the query definition
  3. Create initial state to hold the restaurants array
  4. Query for the restaurants array from our API & update the state
  5. Display the restaurants array in the React application.

Finally, we’ll create the UI for the form fields & button to call the createRestaurant method:

<div style={styles.inputContainer}>
  <input
    name='name'
    placeholder='restaurant name'
    onChange={this.onChange}
    value={this.state.name}
    style={styles.input}
  />
  <input
    name='description'
    placeholder='restaurant description'
    onChange={this.onChange}
    value={this.state.description}
    style={styles.input}
  />
</div>
<button
  style={styles.button}
  onClick={this.createRestaurant}
>Create Restaurant</button>

const styles = {
  // existing styles omitted
  inputContainer: {
    margin: '0 auto', display: 'flex', flexDirection: 'column', width: 300
  },
  button: {
    border: 'none', backgroundColor: '#ddd', padding: '10px 30px'
  },
  input: {
    fontSize: 18,
    border: 'none',
    margin: 10,
    height: 35,
    backgroundColor: "#ddd",
    padding: 8
  }
}

If you’d like a video walkthrough of how to install & configure the AWS Amplify CLI, click here. Now that the CLI is installed & configured, we can initialize a new Amplify project in our React application. From the inside your React application, run the following command:
Now, we should be able to run the app and create new restaurants from the React application:

GraphQL Subscriptions

As I mentioned in the introduction, one of the most powerful features of GraphQL are real-time data with subscriptions.

Subscriptions push data from the server to the clients that choose to listen to the real time data coming from the server. We can subscribe to the creation of a new item, in our case the creation of a new restaurant, & get notified of the creation of the item as well as receive the item data in the subscription callback.

To implement subscriptions, we need to do three things:

  1. Import the APIs from AWS Amplify
  2. Import the query definition
  3. Create initial state to hold the restaurants array
  4. Query for the restaurants array from our API & update the state
  5. Display the restaurants array in the React application.
// import the subscription defition
import { onCreateRestaurant } from './graphql/subscriptions'

// initialize the subscription in componentDidMount
async componentDidMount() {
  // other code from this method omitted
  this.subscription = API.graphql(
    graphqlOperation(onCreateRestaurant)
  ).subscribe({
    next: restaurantData => {
      const restaurant = restaurantData.value.data.onCreateRestaurant
      const restaurants = [
        ...this.state.restaurants.filter(r => {
          return (
            r.name !== restaurant.name && r.description !== restaurant.description
          )
        }),
        restaurant
      ]
      this.setState({ restaurants })
    }
  })
}

// remove the subscription in componentWillUnmount
componentWillUnmount() {
  this.subscription.unsubscribe()
}

When the subscription fires, we do 3 things:

  1. Import the APIs from AWS Amplify
  2. Import the query definition
  3. Create initial state to hold the restaurants array
  4. Query for the restaurants array from our API & update the state
  5. Display the restaurants array in the React application.
Conclusion

In this tutorial we’ve walked through all of the typical GraphQL operations you would use in a real-world application. We’ve also built & deployed a real-world GraphQL API that will automatically scale for you as your application scales.

The only data source we’ve looked at so far is DynamoDB, but AWS AppSync also supports other data sources out of the box (including Amazon ElasticSearch, AWS Lambda, & http resolvers). If you’re interested in learning more about using other data sources, check out the documentation here.

AWS AppSync has 2 JavaScript clients: AWS Amplify (which we have already covered), & the AWS AppSync JavaScript SDK (which we did not cover).

If you are looking for a solution that handles offline data & operations for you, then take a look at the AWS AppSync JavaScript SDK because it’s built in & works out of the box. You can still use Amplify to create & configure the AWS AppSync service while using the AWS AppSync JS SDK to interact with the service.