Next.js Server Action and Sendgrid

Next.js Server Action and Sendgrid

Rant Warning! What is up with everyone and their todo tutorials on Youtube and on almost every blog? All I wanted to do was convert my contact form away from the page router to the app router. I was banging my head on this challenge for a few hours.

So my goal was that I wanted to learn how to use Next.js server action while at the same time converting my contact page form into a server component. Turns out there were a few concepts that I needed to understand and learn.

The first concept, the FormData. This wasn’t too hard to comprehend. The code written can even be very minimal. This gets used on the function you create that you supply to the action attribute of the form element.

Blog Image

If you are anything like me when you’re learning something new, the next move is to console log everything until you figure out how things work. When the function is executed the formData parameter is supplied an object of whatever values were typed into your input fields.

Blog Image

Since we now have an object to work from, we can run methods, specifically get(), on it that are supplied by the FormData interface. What I did was grab the values and place it into another object that I will send out with a Post request.

Blog Image

Here lies the second concept and my biggest hurdle yet. This had me punching the air for an hour or two. I decided to use the fetch API. Like a good little developer, I gave it a path for where it was supposed to go and provided my data object. I used the POST method and stringify the data object in the body of the request.

Blog Image

You would think this should work, right? No, I was stuck just guessing on why this wasn’t working. I had no real error messages on what was going on to even get a clue on how to fix it.

This is when I realized I was being lazy and not including the .then() method in order to catch my success or error messages. This did not fix my problem but it did get me closer by giving me an error message that was useful.

Blog Image

As you can see from the returned error message, ERR_INVALID_URL, you can now pinpoint that the URL being given to the fetch method is probably the issue. What I failed to realize, learning the hard way, was that the fetch method takes an absolute path, http://localhost:3000/exampleForm, and not a relative path, /api.

Blog Image

Once I supplied the fetch method the absolute path and submitted the form we got a success message and a 200 code. This is where the nerd inside me jumped for joy and I remembered why I loved being a web developer.

Blog Image

I now needed to figure out how to supply the fetch method an absolute URL path that didn’t matter if I was on my developer environment or on my production server. This is where a quick Google search introduced me to the Headers Interface that I could use on the backend side. This Header Interface supplies me with methods that I can use to grab the absolute URL path that wasn’t dependent on what environment I was on.

Blog Image

Your final working code for the form action function should end up looking like this:

Blog Image

This leads me to my third and last concept. The new API routes. This concept wasn’t too difficult to understand. For most who were using the page router, you used to create your backend api’s in the page/api location. In the app router, this was moved to the location under the same path as your page component or you can place it in the root directory as well. The code you write is placed in a file called route.js or route.ts. The route file allows you to create custom request handlers for a given route. The following HTTP methods are supported: GET, POST, PUT, PATCH, DELETE, HEAD, and OPTIONS. Since submitting the form wasn’t working at first, this took me a few tries to get correct using the POST request. I was able to determine that I had the path location correct by testing it out with a GET request which only requires you to type the URL location in the browser and you should get back your request.

Blog Image

You should now see the Hello, Next.js message on the page you are loading.

Blog Image

Since I now know that I have the app router api path location correct, I can convert the GET function into a POST function. The key takeaway here is that the POST function receives a parameter that gets supplied with the object of all your form values in it. This is what you’re going to use to feed to the Sendgrid API. I also stringify the returned values of that object.

Blog Image

From there on that was the end of all of my pain points and troubles. The rest of the code was pretty straight forward which I won’t bore you with the details here. You just take the body variable that you created and supply it to the Sendgrid API. Sorry for assuming but it’s just boilerplate Sendgrid code that was copied and pasted over from when I was using the page router API. You can also grab this code from the Sendgrid documentation or copy what I did.

Blog Image

For those of you who are like why didn’t he go through the Sendgrid API code? I will be making a YouTube video that will be explaining this blog post in more details and also including the part of how to use the Sendgrid API code. The main point of this article was to express the pain points I went through so that no one else has to go through it by themself.