Getting started with GraphQL in .NET 6 - Part 3 (Consume with ApolloClient React)

Before your API is ready to consume. You need to update about CORS. I update the Program.cs to have CORS settings. The CORS settings looks like this.

// ...

builder.Services.AddCors(options =>
{
    options.AddDefaultPolicy(
        builder =>
        {
            builder.WithOrigins("*")
                   .AllowAnyHeader();
        });
});

builder.Services.AddControllers();  

// ...


app.UseHttpsRedirection();

app.UseCors();

app.UseAuthorization();

// ...

Note: This settings is not best practice for production. Please setting it up correctly for production. More information please read this documentation.

Our API is ready to consume!

Prepare your Front End

Now, let's start we use our FE client. I will not bring the step by step how to code, since the step will be complex.

  • Prepare your tools, you will need Node.js and yarn for run this frontend code. For node you can visit here, for yarn you can use the v1 is here.

  • Download/clone the repository. For the repository, you can visit here:

GitHub logo bervProject / react-graphql-client

React GraphQL Client Example

Getting Started with Create React App

This project was bootstrapped with Create React App.

Available Scripts

In the project directory, you can run:

yarn start

Runs the app in the development mode.
Open http://localhost:3000 to view it in the browser.

The page will reload if you make edits.
You will also see any lint errors in the console.

yarn test

Launches the test runner in the interactive watch mode.
See the section about running tests for more information.

yarn build

Builds the app for production to the build folder.
It correctly bundles React in production mode and optimizes the build for the best performance.

The build is minified and the filenames include the hashes.
Your app is ready to be deployed!

See the section about deployment for more information.

yarn eject

Note: this is a one-way operation. Once you eject, you can’t go back!

If you aren’t satisfied…

  • Install the dependencies, use yarn install.

  • Run your code. yarn start.

  • Now. Ready to try. :)

  • For demo purpose, you can see this video.

FE Code TLDR;

Some codes that you need to understand are here:

  • Setup client url at Index.tsx:
import ReactDOM from 'react-dom';
import {
  ApolloClient,
  InMemoryCache,
  ApolloProvider
} from "@apollo/client";
import 'bulma/css/bulma.min.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

const client = new ApolloClient({
  uri: 'https://localhost:7298/graphql', // you need setup the URL here, if you have different URL
  cache: new InMemoryCache()
});

ReactDOM.render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  document.getElementById('root')
);

// ...
  • Check the query and mutation implementation at Notes.tsx. You can separate the gql to another folder so you will have good code structure.
import { useMemo, useState } from "react";
import { Button, Columns, Form, Heading } from "react-bulma-components";
import { gql, useMutation, useQuery } from "@apollo/client";

const NOTES_QUERY = gql`
  query GET_NOTES {
    notesFromEF {
      id
      message
    }
  }
`;

const NOTES_MUTATION = gql`
  mutation CREATE_NOTE($message: String!) {
    createNote(message: $message) {
      id
      message
    }
  }
`;

function mapToDataNotes(data: any): Array<any> {
  console.log(data);
  if (data && Array.isArray(data.notesFromEF)) {
    return data.notesFromEF;
  }
  return [];
}

export default function Notes() {
  const [note, setNote] = useState<string>("");
  const { loading, data, refetch } = useQuery(NOTES_QUERY);
  const [createNote, {loading: loadingAdd }] = useMutation(NOTES_MUTATION);

  const addNote = async () => {
    if (!!note) {
      console.log("OK");
      await createNote({
        variables: {
          message: note
        }
      });
      setNote("");
      await refetch();
    } else {
      console.log("ERROR");
    }
  };

  const getDataList = useMemo(() => mapToDataNotes(data), [data]);

  return (
    <>
      <Columns>
        <Columns.Column>
          <Form.Field>
            <Form.Label>Note</Form.Label>
            <Form.Control>
              <Form.Input
                value={note}
                onChange={(e) => setNote(e.target.value)}
              />
            </Form.Control>
          </Form.Field>
          <div className="buttons">
            <Button
              color="success"
              fullwidth
              loading={loading || loadingAdd}
              onClick={addNote}
            >
              Add New Note
            </Button>
            <Button
              color="dark"
              fullwidth
              loading={loading || loadingAdd}
              onClick={async () => {
                await refetch();
              }}
            >
              Refresh Data
            </Button>
          </div>
        </Columns.Column>
        <Columns.Column>
          <Heading>Note List</Heading>
          <p className="content">
            <ul>
              {getDataList.map((note) => <li key={note.id}>{note.message}</li>)}
            </ul>
          </p>
        </Columns.Column>
      </Columns>
    </>
  );
}

Note & Suggestion: You could move and separate the list component if you want it and to have smaller component to handle the mutation.

Backend Code

GraphQL .NET Example

GraphQL example implementation in .NET 6.

LICENSE

MIT

Next Part Plan

For the next part, I am going to post about deployment the API to Azure Web App. Stay tune!

Thank you

Yey, you are connected to API with this frontend code! Thank you for reading. Any suggestions? Feel free to ask.

22