Building a Full Stack App with CRUD

ryanjames1729

Ryan James

Posted on March 1, 2024

Building a Full Stack App with CRUD

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

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>
        )}
Enter fullscreen mode Exit fullscreen mode

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 [];
  }
}
Enter fullscreen mode Exit fullscreen mode

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/ and the repo is available at https://github.com/ryanjames1729/crud-with-forms.

This article was originally posted on https://ryan-james.dev.

💖 💪 🙅 🚩
ryanjames1729
Ryan James

Posted on March 1, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related