So let's get started
working on this website here.
And I wanna start with creating user accounts,
because, of course, we need user accounts first
before we then can log users in.
So, therefore, I wanna make sure
that if we click this Create Account button here,
we submit the entered data,
and I therefor wanna make sure
that only valid data is accepted,
and we create a new user
with that email-password combination.
Now, as I mentioned in the previous lecture already,
this starting project
already comes with a database in the end
that will contain a user's table,
where we need to store a unique email and a password.
So that's exactly what I wanna do as a first step now.
And, therefore, on this auth form here,
I wanna add a Server Action
that handles the form of submission,
where we extract the email-password combination
and store it in the database.
And I actually don't just wanna extract and store that data.
Instead, I also wanna validate it so that we, for example,
catch values that aren't valid email addresses,
or potentially also passwords
which are too short, let's say.
And therefore, as a first step,
I'll add a new folder in this project,
in the root project folder,
and I'll name it actions,
because here, I wanna store my Server Actions
in separate files.
That's of course not something you have to do,
as you learned in this course,
but it is something I will do here.
And therefore here I'll add an auth.js file,
or maybe auth-actions.js to make it clear
that we'll store some Server Actions in there.
The name of course is up to you.
And then in that file, I'll add this 'use server' directive
at the top of this file,
because as you learned in this course,
if you wanna create functions that should serve
as Server Actions in a NextJS application,
you need to add this 'use server' directive here
at the top of the file where you create those functions
or inside of the functions themselves.
And here, since I have a separate file, I add it at the top.
Okay, so that's the first step.
The next step is to create a new async function in here,
and it must be async as you learned.
Server Actions are async functions,
which I'll name, signup.
The name of course is up to you,
but this name should be pretty descriptive
regarding what this function will do.
Well, and then this function
will eventually receive some form data as you learned
since I plan on using it as a Server Action
and since I plan on assigning it to a form.
And then NextJS will automatically provide that form data.
And here, I'll then extract my email from that form data,
with formData.get email,
and my password with formData.get password, like this.
And of course, these names, email, and password,
are not some random names I picked here,
but instead, these are the names you'll find
in the auth form here, assigned to the name attribute.
So, that will allow us to retrieve
the email and the password.
And with that retrieved,
we of course eventually wanna store it in the database,
so we want to create a new user.
But first, I wanna validate that data.
And there would be various ways of doing that.
I'll validate that data by creating an errors object,
which initially is an empty object.
And I'll then check if my email
does not include an @ symbol.
So a pretty basic check, but better than nothing.
And if that's the case,
I wanna add a new field to that errors object,
let's say, a field named, email,
which contains the error message.
And in my case here, that will be,
"Please enter a valid email address,"
or something like this.
So that's the first check.
The next check is to check if the password,
after trimming it to remove excess wide space
at the beginning or end,
if it then has a length
that's smaller than eight, let's say,
so that we force the user to pick a password
that's at least eight characters long for security reasons.
So if we have a shorter password,
I'll add a password field to the errors object.
And in there, we could have an error message like,
"Password must be at least 8 characters long,"
to tell the user what's wrong.
Though of course, just by creating this errors object,
we won't do anything.
Instead, we of course, need to kind of pass this object here
to our front end to our form and output it there.
And you did learn in this course how that can be achieved
with help of the use form state hook.
So, here in the auth-form.js file,
we can actually import something from react-dom
and that something is the use form state hook,
about which you learned earlier in the course already.
There, you also learned that this hook
only works in a client component,
and therefore I'll add the 'use client' directive here,
at the top of the auth-form.js file.
Well, and then with that,
we can call use form state here in the auth form.
And we now need to pass the Server Action
that should be handled with help of the use form state hook
as a first argument to that hook.
And that Server Action, of course,
is that signup action I'm working on here.
Therefore, we should actually export this function
from the auth actions file,
so that in auth-form.js we can import it,
and import this signup function from the actions folder
and the auth actions file.
And it's then this signup action that will be passed
as a first argument to use form state.
The second argument as you learned is the initial state,
and in my case here, that will be an empty object.
And then we'll get back an array with exactly two elements,
where the first element will be the form state,
and the second argument will be the action.
So, this signup action
but actually wrapped with an extra function essentially
that allows React to listen to that action
and manage this form state for us.
So it's then this form action
that should be assigned to the form as an action
through the action prop, like this.
And it's then the form state
that can be used to output the potential error messages
we might be getting due to incorrect values.
And here in this form, I wanna output those errors
above my submit button here.
And here, I'll check if my form state has an errors key.
Initially, it's an empty object with no keys,
but I plan on adding an errors key here
in the signup function soon.
It's not there yet, but it will soon be there.
Therefore, this form state should actually be
an object with an error key
if we have some validation errors.
And therefore, here, I'll check if that's truthy.
So if we have an error key with some values.
And if that's the case,
I wanna output an unordered list
with an ID of form-errors,
and that's an ID you should add for styling purposes.
And in that list, I'll then output
those various errors messages we might have.
And I expect errors to be an object
that will have this shape.
So, an object that has an email or a password key,
or both, depending on what's invalid.
And we can therefore map those keys
in that errors object to list items
by using Object.keys,
which is a method built into JavaScript,
which in the end converts a list of keys into an array.
We pass the form state errors object to it,
and that will then give us an array of those keys,
so of those key value pairs
that are stored in that errors object.
And here, I can then go
through those different key value pair objects.
And for every key value pair object,
I'll render a list item
where the key should be the key name here.
So that will in the end just be the key name
of the different keys we're going through here
for this errors object.
And the value I then wanna output here for that list item,
well, that will be formState.errors.
And then I access the value for this specific key
we're currently looking at.
So the key here, error, will be email or password,
since these will be the only keys I add to this object,
and the values will then be the error messages.
And it's these errors which output here.
So that should then output
any validation form errors we might have,
but we're not done yet.
This is an important first step,
but as you learned,
if you wrap an action with use form state,
you need to tweak that Server Action function a little bit,
because it will now no longer directly get the form data,
or it will not just get the form data.
Instead, it will now actually get two arguments,
two parameters
where the second parameter will be the form data,
and the first parameter will be the previous form state.
Now, I don't need that here,
but we still need to accept it
to make sure that we correctly extract that form data.
It must be the second parameter here.
And, of course, I now also must return this errors object
stored under a key named, errors,
so that this code does its job.
Hence, in the auth-actions.js file,
I wanna check, after running these checks here,
if I got any errors
because we don't necessarily have any.
After all, we could make it pass both if checks here
without having any error,
if the user did enter valid values.
But we will know that we have at least one error
if we have the email or password key in that object.
Or to put it in another way,
if we have any keys at all in that errors object.
So I'll add a third "if" check here,
and check if the keys in that errors object...
Keep in mind this converts
the key value pairs of that object to an array
if that array has a length that's greater than zero,
which means we have at least
one key value pair in that object,
which will only be the case
if at least one of those checks failed.
So if we made it into at least one of those "if" statements.
So if we have at least one key in the errors object,
I know that at least one invalid value has been entered.
And in that case, I wanna send back a new object
as a response.
As you learned, whatever you return in a Server Action
will be sent back as a response to the client,
and this object will then become the new form state.
So the new value exposed
through that form state variable here in our auth form,
that should be an object with a key of errors
to show those errors.
So, therefore, I'll add a key named, errors, to this object,
and the value stored under that key
should be this errors object.
So it has the same name.
And if the key name
and the variable or a constant name that holds the value
that should be stored under the key are the same,
you can actually shorten that in JavaScript
and write it like this.
And that's now the validation code I wanna add.
The validation code in the Server Action
and the code in the auth form
to show those validation errors.
With that, if you save this,
if you save all files and you reload this page,
for example, enter a valid email address.
But if the password is too short
and you click Create Account,
you should see this error message.
Now, if you enter a valid value,
so a valid email and a valid password,
you'll actually get an error
because we're not handling that case yet.
That scenario, that's the user entered a valid value.
But that's what we'll do next.
Because it's of course in that scenario,
that valid values we're entered,
that we wanna create a new user,
store it in the database,
and do a bunch of other things.