GraphQL - ReactJS | Add Data
Tags: graphql, react, javascript, webdev
Published: 2023-08-21 13:39:28

Hello Everyone, in this part of the GraphQL series, we are going to fetch data using the Apollo Client package.

### Inside the "Queries.ts" file which we had created in previosu part, add this code at the bottom.
```js
export const CREATE_USER = gql`
  mutation CreateUser($newUser: CreateUser!) {
    createUser(newUser: $newUser) {
      role
      name
      isEmployee
      age
    }
  }
`;

export const UPDATE_USER = gql`
  mutation UpdateUser($updatedUser: UpdateUser!) {
    updateUser(updatedUser: $updatedUser) {
      id
      name
      role
      age
      isEmployee
    }
  }
`;
```

So we have created a query for Adding a user with role,name, isEmployee and age fields and same for Updating a user

### Imports
```js
import { useMutation } from "@apollo/client";
import { CREATE_USER, UPDATE_USER, ALL_USERS } from "./Queries";
import { useCounterStore } from "./UsersList";
```
* We have imported useMutation hook to attach the method with onClick and onSubmit event handlers
* CREATE_USER, UPDATE_USER and ALL_USER are our queries
* useCounterStore from our UserList component to access states and their setter functions

### Accessing the states and setter functions
```js
...
const CreateUser = () => {

  const id = useCounterStore((state) => state.id);
  const name = useCounterStore((state) => state.name);
  const setName = useCounterStore((state) => state.setName);
  const age = useCounterStore((state) => state.age);
  const setAge = useCounterStore((state) => state.setAge);
  const role = useCounterStore((state) => state.role);
  const setRole = useCounterStore((state) => state.setRole);
  const isEmployee = useCounterStore((state) => state.isEmployee);
  const setIsEmployee = useCounterStore((state) => state.setIsEmployee);
  const isUpdate = useCounterStore((state) => state.isUpdate);
  const setIsUpdate = useCounterStore((state) => state.setIsUpdate);

...
```

### Input fields handler methods
```js
...

const handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setName(event.target.value);
  };

  const handleAgeChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setAge(Number(event.target.value));
  };

  const handleOptionChange = (
    event: React.ChangeEvent<HTMLInputElement>
  ): void => {
    setIsEmployee(event.target.value === "true");
  };

  const handleRoleChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
    setRole(event.target.value);
  };

...
```
* Creating handler method for each input

### Creating methods for add and update user
```js
...

 const [createUser] = useMutation(CREATE_USER, {
    refetchQueries: [{ query: ALL_USERS }],
  });

  const [updateUser] = useMutation(UPDATE_USER, {
    refetchQueries: [{ query: ALL_USERS }],
  });

...
```
* createUser and updateUser are our methods which we can attach to our event listeners, inside useMutation, we have 2 params, first one is the query itself, second one is a refetch method, so whenever we add or update a user, ALL_USER query will run along with it and display the latest data in real time.

### Form inputs
```js
...

return (
    <form className="flex flex-wrap items-center justify-center gap-5 py-5 px-4 bg-gradient-to-r from-slate-800 to-black">
      <div className="flex gap-4 justify-between w-full md:w-fit items-center">
        <label className="font-semibold text-white">Name</label>
        <input
          className="border border-blue-400 px-2 py-1 w-52 rounded-2xl"
          type="text"
          value={name}
          onChange={handleNameChange}
        />
      </div>
      <div className="flex gap-4 justify-between w-full md:w-fit items-center">
        <label className="font-semibold text-white">Age</label>
        <input
          className="border border-blue-400 px-2 py-1 w-52 rounded-2xl"
          type="number"
          value={age}
          onChange={handleAgeChange}
        />
      </div>
      <div className="flex gap-4 justify-between w-full md:w-fit items-center">
        <label className="font-semibold text-white">Role</label>
        <select value={role}
          onChange={handleRoleChange}
          className="border border-blue-400 px-2 py-1 w-52 rounded-2xl">
            <option> WebDeveloper</option>
            <option>Tester</option>
            <option>SoftwareEngineer</option>
        </select>
      </div>
      <div className="flex gap-4 justify-between w-full md:w-fit items-center">
        <p className="font-semibold text-white">Employee</p>
        <label className="text-white">
          <input
            type="radio"
            value="true"
            checked={isEmployee === true}
            onChange={handleOptionChange}
          />
          True
        </label>

        <label className="text-white">
          <input
            type="radio"
            value="false"
            checked={isEmployee === false}
            onChange={handleOptionChange}
          />
          False
        </label>
      </div>

...
```
* We have created 2 input fiels for name and age, select field for role and radio inputs for employee status.

### Button condition for Add or Update
```js
...

   <div className="flex justify-center w-full md:w-fit ml-4 md:ml-0">
        {isUpdate ? (
          <>
            <button
              className="px-4 py-2 rounded-lg bg-blue-400 text-white"
              onClick={(e) => {
                e.preventDefault();
                if (name === "" || role === "") {
                  alert("Fill all the details");
                } else {
                  updateUser({
                    variables: {
                      updatedUser: {
                        id,
                        name,
                        age,
                        role,
                        isEmployee,
                      },
                    },
                  }).then(() => {
                    setName("");
                    setAge(18);
                    setRole("");
                    setIsEmployee(false);
                  });

                  setIsUpdate(false);
                }
              }}
            >
              Update
            </button>

            <button
              className="px-4 py-2 rounded-lg bg-red-400 text-white ml-3"
              onClick={() => {
                setIsUpdate(false);
                setName("");
                setAge(18);
                setRole("");
                setIsEmployee(false);
              }}
            >
              Cancel
            </button>
          </>
        ) : (
          <button
            className="px-4 py-2 rounded-lg bg-blue-600 text-white"
            onClick={(e) => {
              e.preventDefault();
              if (name === "" || role === "") {
                alert("Fill all the details");
              } else {
                createUser({
                  variables: {
                    newUser: {
                      name,
                      age,
                      role,
                      isEmployee,
                    },
                  },
                }).then(() => {
                  setName("");
                  setAge(18);
                  setRole("");
                  setIsEmployee(false);
                });
              }
            }}
          >
            Add
          </button>
        )}
      </div>
...
```
* We are checking for a isUpdate state, if it is true, show update button with updateUser method and if it is false, show add button with createUser method.Inside both the methods for create or update user, we have variable object and inside it we have the object with name same as the query param name which is "newUser" for createUser and "updateUser" for updateUser We are going to control this state from Display Component which we will discuss in next part of this series.


## Complete code
```js
import { useMutation } from "@apollo/client";
import { CREATE_USER, UPDATE_USER, ALL_USERS } from "./Queries";
import { useCounterStore } from "./UsersList";

const CreateUser = () => {

  const id = useCounterStore((state) => state.id);
  const name = useCounterStore((state) => state.name);
  const setName = useCounterStore((state) => state.setName);
  const age = useCounterStore((state) => state.age);
  const setAge = useCounterStore((state) => state.setAge);
  const role = useCounterStore((state) => state.role);
  const setRole = useCounterStore((state) => state.setRole);
  const isEmployee = useCounterStore((state) => state.isEmployee);
  const setIsEmployee = useCounterStore((state) => state.setIsEmployee);
  const isUpdate = useCounterStore((state) => state.isUpdate);
  const setIsUpdate = useCounterStore((state) => state.setIsUpdate);

  const handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setName(event.target.value);
  };

  const handleAgeChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setAge(Number(event.target.value));
  };

  const handleOptionChange = (
    event: React.ChangeEvent<HTMLInputElement>
  ): void => {
    setIsEmployee(event.target.value === "true");
  };

  const handleRoleChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
    setRole(event.target.value);
  };

  const [createUser] = useMutation(CREATE_USER, {
    refetchQueries: [{ query: ALL_USERS }],
  });

  const [updateUser] = useMutation(UPDATE_USER, {
    refetchQueries: [{ query: ALL_USERS }],
  });

  return (
    <form className="flex flex-wrap items-center justify-center gap-5 py-5 px-4 bg-gradient-to-r from-slate-800 to-black">
      <div className="flex gap-4 justify-between w-full md:w-fit items-center">
        <label className="font-semibold text-white">Name</label>
        <input
          className="border border-blue-400 px-2 py-1 w-52 rounded-2xl"
          type="text"
          value={name}
          onChange={handleNameChange}
        />
      </div>
      <div className="flex gap-4 justify-between w-full md:w-fit items-center">
        <label className="font-semibold text-white">Age</label>
        <input
          className="border border-blue-400 px-2 py-1 w-52 rounded-2xl"
          type="number"
          value={age}
          onChange={handleAgeChange}
        />
      </div>
      <div className="flex gap-4 justify-between w-full md:w-fit items-center">
        <label className="font-semibold text-white">Role</label>
        <select value={role}
          onChange={handleRoleChange}
          className="border border-blue-400 px-2 py-1 w-52 rounded-2xl">
            <option> WebDeveloper</option>
            <option>Tester</option>
            <option>SoftwareEngineer</option>
        </select>
      </div>
      <div className="flex gap-4 justify-between w-full md:w-fit items-center">
        <p className="font-semibold text-white">Employee</p>
        <label className="text-white">
          <input
            type="radio"
            value="true"
            checked={isEmployee === true}
            onChange={handleOptionChange}
          />
          True
        </label>

        <label className="text-white">
          <input
            type="radio"
            value="false"
            checked={isEmployee === false}
            onChange={handleOptionChange}
          />
          False
        </label>
      </div>
      <div className="flex justify-center w-full md:w-fit ml-4 md:ml-0">
        {isUpdate ? (
          <>
            <button
              className="px-4 py-2 rounded-lg bg-blue-400 text-white"
              onClick={(e) => {
                e.preventDefault();
                if (name === "" || role === "") {
                  alert("Fill all the details");
                } else {
                  updateUser({
                    variables: {
                      updatedUser: {
                        id,
                        name,
                        age,
                        role,
                        isEmployee,
                      },
                    },
                  }).then(() => {
                    setName("");
                    setAge(18);
                    setRole("");
                    setIsEmployee(false);
                  });

                  setIsUpdate(false);
                }
              }}
            >
              Update
            </button>

            <button
              className="px-4 py-2 rounded-lg bg-red-400 text-white ml-3"
              onClick={() => {
                setIsUpdate(false);
                setName("");
                setAge(18);
                setRole("");
                setIsEmployee(false);
              }}
            >
              Cancel
            </button>
          </>
        ) : (
          <button
            className="px-4 py-2 rounded-lg bg-blue-600 text-white"
            onClick={(e) => {
              e.preventDefault();
              if (name === "" || role === "") {
                alert("Fill all the details");
              } else {
                createUser({
                  variables: {
                    newUser: {
                      name,
                      age,
                      role,
                      isEmployee,
                    },
                  },
                }).then(() => {
                  setName("");
                  setAge(18);
                  setRole("");
                  setIsEmployee(false);
                });
              }
            }}
          >
            Add
          </button>
        )}
      </div>
    </form>
  );
};

export default CreateUser;
```

In the next part of this GraphQL series, we will cover the update and delete feature for our data using "useMutation" hook.
THANK YOU FOR CHECKING THIS POST
You can contact me on -
Instagram - https://www.instagram.com/supremacism__shubh/
LinkedIn - https://www.linkedin.com/in/shubham-tiwari-b7544b193/
Email - shubhmtiwri00@gmail.com

^^You can help me with some donation at the link below Thank you👇👇 ^^
☕ --> https://www.buymeacoffee.com/waaduheck <--

Also check these posts as well
https://dev.to/shubhamtiwari909/website-components-you-should-know-25nm

https://dev.to/shubhamtiwari909/smooth-scrolling-with-js-n56

https://dev.to/shubhamtiwari909/swiperjs-3802

https://dev.to/shubhamtiwari909/custom-tabs-with-sass-and-javascript-4dej