Okay, let's now solve this together.
We wanna add a couple of API routes here
so that we can have our own server-side logic
which is detached from rendering pages.
And you'll learn how that works.
In the pages folder
you add that special API folder, which has to be called API.
And in there you can now again create
any file and folder structure of your choice
to define the different API routes and the paths
leading to those routes you wanna use.
For example, we could add a newsletter JS file
for the newsletter related logic.
Then you learn that an API route in the end just is
a function inside of that API route file
which you should export like this.
And this function receives a request and the response object
automatically passed in by next JS
when it executes this function for incoming requests.
Here we can then check the request method, for example
to only proceed for a post requests.
And we can do this here for the email registration
because whilst this is the only kind of method
I wanna support here
I wanna make sure that no other method
triggers any logic here.
So I explicitly check if the incoming request
is a post request and I only wanna proceed in that case
because in that case I for example also know
that I can extract data from the request body.
Because for example, get requests would not carry any data.
So with that, we can extract data from the request body
and we can do it as with the request body field
as you learned.
Here, we could then expect that we have an email field
and that's up to you.
You are the developer of this site.
So it's up to you, how you transmit your data.
And I will therefore expect an email field.
So the user email is then extracted
from the incoming request.
Now here we could then also validate this
and check if it's maybe not valid or
if email,
user email I mean
does maybe not include @ symbol.
Which is a very basic email validation
you might want to implement more (indistinct) one
but it's a start.
And such server-side validation is optional
but strongly recommended.
Because even if you add validation and checks
in your front-end code, those validation steps
can always be circumvented.
After all all your front-end code is exposed to your users
so they could also manipulate it.
So you shouldn't rely on front-end validation
front-end validation is always just a convenience feature
for your users.
Instead to really make sure that you get valid data
and that you work with valid data
you should validate in your API route
because this code can't be viewed or changed by your users.
Now for this task here, it's optional.
I did not tell you to add such validation.
So if you did not do that, that's totally fine.
I just wants to bring it up here
because it is important is to be aware of the role
server-side validation plays.
Now, here we could then return to cancel
the (indistinct) function execution if we make it in here.
So if we have invalid data and we could return a response
with a status code of 422
which is a status code signaling that
the user input was bad, and then maybe set a message of
invalid email address.
Something like this.
And we would send this response back to the user
if the input is invalid.
And there after I return to cancel the function execution
because I will add more code after this if check
and I don't want to execute that code
if we have invalid input, hence the return statement.
Now, if we do make it past this if block though
we know that we do have a valid user input
and then we could store it in a database
or anything like that.
And for the moment we'll not do this
for the moment I'll just console log, that user email.
And that is now a first API route
as we could write it.
An API route for extracting an incoming email address.
Now we wanna send a request to this API route
and we wanna do that
from inside the components input folder
from inside the newsletter registration file.
Here we have the registration handler
which is triggered when the form is submitted.
And here I am preventing the browser default then
to a wide that the page has reloaded.
Now we could also validate the user input here
and show an error message if it is invalid
again, validation here is then just a convenience feature
to show some feedback to the user quickly.
It's not something you should rely on
and it's not something I will add here
because it has nothing to do with API routes
but of course feel free to add it in your solution.
Now, in my case here, I will not add it.
I instead wanna send that HTTP request to the API route
we just added.
And again we can, for example
do this with the fetch function
which is built into the browser.
Now for the URL you'll learned that the API route
is hosted by the same server as our pages are
sent back from so it's the same domain.
And hence can just construct an absolute path
to the API route with /api/newsletter in this case.
/newsletter because I named my API route file, newsletter.
If you named it differently you have to use
a different identifier here in your URL.
Now we wanna send a post request
because we need to add some data to the outgoing requests
and hence here all at this configuration object to fetch
where we can set methods to post and then add a body.
Now, speaking of that body, we need to get access to the
input value here.
And there are two main ways of doing that
we can add state and update the state with every keystroke
or we use a ref and I'll do the letter
since I only need access to the input once
when the form is submitted.
So for this I'll use useRef,
which we need to import from react
and we can create our email inputRef here
like this
and then connect it to the input element.
By adding the special ref prop and pointing at email
inputRef like that.
Now this is connected
and now here we can extract our entered email
inside of this registration handler.
We can get the entered email
by reaching out to the email inputRef.current
because that's how refs work
.value to get the currently entered value.
And that's then what I wanna send to the back-end.
Now we need to send our data as JSON data here.
So call JSON.stringIfy.
And I'll pass in an object where I set a email property
to entered email.
And this should be a email property
because in the API route
I'm extracting a email property on my body.
So I'm looking for a email property in my body.
So if you chose a different identifier here
for extracting the data
you also need to choose a different property
when you send the data.
I'm using email so I'm using it in both places.
And then last but not least, I'll add headers
and set a special content type header like this
and set this to application json
to make the API routes aware of the type of data
my request body will carry.
And that will be json data, because I convert my data
to json with JSON.stringify.
So this sends a request to the API route
and now we can of course handle the response
and then the response data if we want to
so here I'll just get access to the response
data
by calling the json method.
And then here we can console log that data
to just console log the response.
And speaking off the response
there's one thing missing in the API route.
I do send the response here
if we have an invalid email address
but we should absolutely also send the response
if we have a valid one.
So in this scenario, after console logging the entered email
I'll send a response with a status code of 201
which means success, a resource was added.
So the email was stored.
And then we can send back any kind of data,
like for example @json object.
So a JavaScript object converted to json
with help of that json method.
Where we add a message property where we could say
signed up.
Anything like this.
If we do that and save this
we can check if this works.
If we reload our application and open our
developer tools
if I enter something invalid here
I get a warning from my browser, actually,
because this is of type email.
So we have to add something valid here as well.
Though that could be disabled in the browser.
So we should not rely on it.
But if I do enter a valid email address here
and I click register, that's looking good
because I'm printing that response data here
which says signed up.
And then the network tab, we also see that
this request was sent successfully
and that we got this 201 status code back.
And if we have a look at our service side terminal here
so this terminal where we started npm run (indistinct)
where all our service-side logs will be printed
we see that test@test.com is output here
and that makes sense because we are console logging
the arriving email address here in our API route.
So this is now working and you can certainly enhance this
and improve error handling or do anything like that
but this is the core functionality
which you should add here
as your first task.