Building a Full Stack App with CRUD
Tags: webdev, nextjs, graphql, typescript
Published: 2024-03-01 01:11:26

## Building a CRUD App
I’ve been using NextJS for a good bit now building my web applications. For my personal site and other applications I felt really comfortable using the Pages router. With some of the newer features that started in version 13 and now in 14, I figured I need to start getting used to the App router. As a computer science teacher, I think that building an application that uses CRUD (create-read-update-delete), is a great way to understand a lot of programming concepts from arrays, objects, sorting data, filtering data, and mutating data. So, I took it on myself to do this for myself. In this guide, I’ll share what I learned about building a full-stack application using NextJS 14 with a GraphQL CMS.

## What Did I Use to Start
To get started on my project, I created a NextJS app with the latest build where I used Typescript and TailwindCSS. In addition I installed the `graphql-request` library using npm. I got rid of the boilerplate for the page on the ‘/’ route. I created a readme section at the top, some toggle buttons for the type of request, a form, and a footer component. I have the form set up so that it changes based on which toggle button is being selected.

![Screenshot of the form](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tuqdg77a0i0u1d6abgv3.png)

## Setting Up the Form
Like I indicated, the toggle buttons change how the form shows up. When each of the inputs gets checked the other ones get unchecked and that triggers a new form to be shown. Using React’s useState makes this really simple. Then using the state of the variable that is set by the checkbox makes the form change. You can see the implementation for the form below.
```
{ read && (
        	<form onSubmit={async (event) => {
          	event.preventDefault()
          	const names = getNames(readName)
          	setUsernames(await names);
        	}}>
        	<label htmlFor="read">
          	<span>Read</span>
          	<input type="text" name="readName" id="readName" placeholder="Read Name goes here" value={readName} onChange={e => setReadName(e.target.value)}/>
          	<span></span>
          	<button type="submit">Read</button>
        	</label>
      	</form>
    	)}
```
To get this working the way I wanted it to, I have React changing the value of my variable `readName` as the client types in the form. Then, when the form is submitted, instead of it performing a typical POST request and sending the form data, I call an asynchronous function that I have on another file, actions.tsx. This part was something that was new for me.

In the past using the pages router with NextJS, I was used to using static props. I could pass props in from the same javascript file or from another one in my app directory without any problems. The new thing for me was that if you use any React hooks, your file or function needs to only use the client by adding the `'use client'` declaration. That is how I had my form set up. So, then all of my asynchronous requests for my GraphQL CMS had to use the server by adding the `'use server'` declaration. You can’t use both at the same time. But, by separating them like components, it tells your app what requests/work that you want to be done where: server or client end.

To get my data fetching and mutating working correctly, remember I had my functions on my actions.tsx file. Below you can see how I set up my function for fetching names from my CMS.
```
export async function getNames(name: string) {
  const endpoint = process.env.GRAPHQL_PUBLIC_ENDPOINT ? process.env.GRAPHQL_PUBLIC_ENDPOINT : '';
  const graphQLClient = new GraphQLClient(endpoint);
 
  const searchname = name ? name : "";
  console.log("name", searchname)
 
  try{
	const { usernames }: any = await graphQLClient.request(`
	query Usernames($searchname: String!) {
  	usernames(where: {name_contains: $searchname}) {
    	id
    	name
    	points
  	}
	}
	`, { searchname }); // variables must be part of the request arguments!
	console.log(usernames);
	return usernames;
  }
  catch (e) {
	console.error(e);
	return [];
  }
}
```

With this function, it fetches the names that it's looking for in the CMS and returns the array of usernames back to the main page. The main page when it receives those names will show them under the form using React hooks.

## Wrapping It Up
This project was really meaningless. I’m never going to use it for any other projects but as a reference for myself. But, it was a lot of fun trying to learn some of the newer features in NextJS 14, really understanding React hooks, and knowing how to properly set up forms. Now, this still may not be the best way to set up forms. But for me as a self-taught developer, I’m very happy with how this turned out.

You can see the site live at [https://crud-with-forms.vercel.app/](https://crud-with-forms.vercel.app/) and the repo is available at [https://github.com/ryanjames1729/crud-with-forms](https://github.com/ryanjames1729/crud-with-forms). 

This article was originally posted on [https://ryan-james.dev](https://ryan-james.dev).