Getting started with GraphQL in .NET 6 - Part 3 (Consume with ApolloClient React)
Tags: dotnet, react, typescript, apolloclient
Published: 2021-11-27 10:58:55

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.

```csharp
// ...

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](https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-6.0).

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](https://nodejs.org/en/download/), for yarn you can use the v1 is [here](https://classic.yarnpkg.com/en/docs/install#windows-stable).

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

{% github bervproject/react-graphql-client %}

* Install the dependencies, use `yarn install`.

* Run your code. `yarn start`.

* Now. Ready to try. :)

* For demo purpose, you can see this video.

{% youtube DMN2TveU-5I %}

## FE Code TLDR;

Some codes that you need to understand are here:

* Setup client url at `Index.tsx`:

```jsx
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.

```jsx
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

{% github bervProject/GraphQLNETExample %}

## 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.

![Awesome GIF](https://media.giphy.com/media/HS0rv0xWpnkMkKGG7f/giphy.gif)