>> Scott Moss: So you got to get all these imports.
Let's go ahead and get all these imports.
We probably already have, I think we only have link in here maybe, yeah.
So I'll talk about these imports.
Use action state, I already talked about it.
You can go look at the docs if you want.
Use router just by the name use, you know it's a hook.
This is a hook to use, next, this is how to use the router programmatically.
We talked about the link component and that's how you click on something in link.
But how do you navigate programmatically?
You got to get a handle of the router and to do that is you do use router, and
now you can navigate programmatically by manually calling router.push,
router.replace, those type of methods that exist on a client side router.
So this is just to get a handle to the router.
Have a button component.
I went ahead and created some form stuff.
There's literally nothing special going on in here.
They're just encapsulating style.
I just don't want you guys having ugly forms.
So, I went ahead and made them nice for you.
But you can go look at them, they're just regular form stuff,
nothing special about them.
There's a toast component here that shows a notification that basically displays
the messages from the server actions when a message is sent,
that's really all it does.
And then, here we go, we got our sign up thing which I think I didn't camel case.
So I'll go back and fix that.
And then we have this type action response.
So, let me go back and fix that on mine should be sign up with a camel case.
And for all the types your people, there you go, I'll put type there, so
you don't lose your minds, there you go.
Okay, obviously all this stuff is red because I'm not using it.
So let's use it, I think all we have to do is somewhere in here,
somewhere in here, I think it's here.
We need to set up our action state, let's do that first and
then we'll do everything.
So let's get our initial state.
Our initial state is essentially just going to be like,
what is the default state of this action?
So in this case, like the form,
what is the initial state that we're gonna get back?
So I can say, what is the default state here?
I mean, you would pretty much do the same thing if you were doing
usestate with a form.
You would have like a default state for things.
So, I'm just gonna say, success is false.
We haven't done anything, there is no message and there are no errors.
Just so we have that.
Cool, that's our initial state.
And then what we wanna do is, we wanna go ahead and get a handle on our router.
Like that.
Then now you can see if you do router., you get those methods that I talked about.
Back, forward, prefetch, push, refresh, replace.
Just programmatically navigating the router.
I'm going to get rid of this use client right quick.
And I'm gonna try to go to this page.
Let me see what happens.
Just so you guys can see.
Let me go to sign up.
Is this off?
I got to turn it on?
Turn that on.
Go here, and try to refresh.
It breaks, right?
Because it says, you're importing a component that needs use router.
This react hook only works in a client component to fix, mark the file, or
its parent with the use client directive.
So this is a page, so it doesn't really have a parent.
So I have to put it here, I got to put use client here, and now it works.
As soon as you try to use a hook, you have to put use client.
Okay?
And that's the hook that I'm using.
All right, so now we're going to set up our action state.
The way this works is, you basically it's gonna
give you this ability to provide a callback.
This callback is the function that's gonna run when the form is
technically submitted.
So when the form is submitted, run this function,
that's basically what's happening here.
And then what you get in return is an array of the current state of the form.
So you can think of the state as in it's the thing that we return from the action.
So, in that case, it's this action response, right, so
it'll be this shape, that's the state.
You also get back the form action itself.
And then the status, is it pending or not?
Is it still going or is it done, right?
So, let's do that.
Use action states, we can type check
this with passing in these generics.
If you don't know what a generic is in typescript is like arguments for types.
So we can pass in the action response, that's gonna be the state type.
And then form data is, I'm guessing the form action type,
let's see, I don't remember.
So we can say, action response and then form data, there we go.
Call it like this, it's an async function, there we go.
Yeah, it takes in a second argument for initial state.
So I'll pass in the initial state here.
Or is it an array initial state?
No, it's just initial state, okay, so many hooks, initial state, there we go.
Okay, so now we have our state, we have our form,
or let's call it form action, I guess.
And then we have our, what did I call it here?
Yeah, is pending, so, there we go.
So what do we wanna do in here?
We just wanna call sign up, that's like the number one thing we wanna do.
And then depending on that, we'll show a toast or
we'll navigate you somewhere if it's successful.
So in this case, we can say result equals await,
we're gonna call sign up.
Like this, signup takes in the form data.
We can get the form data from what's gonna be passed in here as an argument.
So, the two arguments you get are gonna be the previous state and then the form data.
So, we'll say, previous date,
which is always gonna be the same type that we're declaring here.
So action response and then the form data.
Because we're gonna add this to a form, is always gonna be form data here.
So I can just pass that in like that.
Once we have that result, we can handle success.
So if it's a success, we want to call a toast success, show a message and
then route you to the dashboard.
Congratulations, you just signed up.
So if result.success,
we wanna say toast.success.
What did I put there?
Account created, Successfully,
and then router.push, I mean,
technically probably wanna do a replace here,
but push is fine to slash dashboard, there we go.
This is terminal, it has a void.
So you don't have to put a return here.
Nothing will happen after this.
If I put some code here, it's gonna be unreachable.
It actually might even, it should show me that.
Let me see.
Maybe not, but yeah, you don't have to put a returner, it's good.
Yeah, just return the results.
Otherwise, we could do a try catch here, I guess just to handle the errors.
So if there is an error, we'll just return this.
Cool, it wants errors maybe.
Yeah, I'm not doing all that, it's fine, [LAUGH] you'll be okay.
So now we need to actually implement this into our jsx.
So we need to implement, we need to show the errors, we need to do all that stuff.
So right here, I have all the form stuff.
We can just go ahead and copy this, don't type all this stuff out,
it's pretty simple.
So grab all the form stuff.
And we'll go through it.
So I think down here where we wanna put this,
is like right above this div, I think.
I mean, it's gonna look good, it's gonna look bad, we're gonna find out, cool.
So let's walk through this right quick because it's pretty simple,
just creating a form.
The most important part is that we pass our form
action that we get from our use action state.
So this action, which is a handler for this form function,
essentially, we wanna pass that to the action prop on the form.
This is not a magical prop, that's for this form component.
Every form in HTML has a prop called action on it.
This is the handler to the action.
This is where I show any error.
So if the state has a message and there's no success, then show a form error.
So we can show the user the error message.
And then out here, this is how we map the names of,
you remember we were doing formdata.getemail, formdata.getpassword,
okay, you have to put a name on that, that's how it gets it.
This is what's creating the formdata, this name matters.
So, everything else is standard HTML5 form inputs, there's nothing,
I mean, this is also standard HTML5 inputs.
I'm just letting you know how it maps to form data, which is not related to nxtjs,
that's also just HTML5 forms.
There's nothing special here,
even though the client side validation on the inputs is just regular HTML5 inputs.
There's nothing crazy here.
Notice this is not a controlled input, there's no onchange, you probably like,
where's the on change?
Where's that?
No, there's no unidirectional data flow, there's no controlled inputs,
we don't need that.
It's done, it's out of here.
At least for submitting forms,
you'll still need that if you need to validate stuff as you go.
But for submitting a form, you don't need controlled inputs anymore,
which is crazy, cuz that's not how it's been taught forever.
And then yeah, disable it if we're still pending.
This will be true as long as this function is still running.
So, this will be true.
And yeah, show some different color borders if there's errors for
that specific field, that's pretty much it.
Same thing for the password, same thing for the confirmed password,
it's all the same thing.
Cool, and the most important part here is this button with type submit.
This is what kicks it off, this is what fires the action when you click it, right,
or you can hit Enter.
>> Learner: It's sort of unrelated, but do you see Use Action state?
That new React stuff kind of taking over like formic and react form.
Is there much use for those libraries anymore with this?
>> Scott Moss: Yeah, I don't know why you would ever use them to be honest.
Outside, like I said, there is still a special use case for
using forms client side and forms that are not just for submitting to a server.
But maybe you typing in something, I don't know if you're making Google Doc and
that's some type of form, you probably still want to use some type of form,
some client side thing.
But for the case of filling something out and submitting it to a server,
I don't know why I would ever use that validation.
Sweet, I get some decent validation here, also validate on a server.
I guess if you want it more input masking or validating as you type,
then you still might need those controlled inputs.
But like I said, for most use cases, just I'm filling out a form and
I'm submitting it.
Probably not, no, yeah.
>> Learner: I have a question around that form action prop.
>> Scott Moss: Yeah. >> Learner: I know that the action prop is
like each inbuilt into HTML forms, but in terms of the form action
along with that being like an async server action and everything like that.
Is there anything that nxt is doing behind the hood to kind of like
polyfill that prop on a form to do any extra magic under the hood?
>> Scott Moss: I don't think it's actually touching that, I could be wrong, but
I'm pretty sure it's not touching that.
In this example, what's happening is, this is just a regular client side
function that when called calls the referenced, this is like doing a fetch.
This is essentially like,
I'm doing a fetch to a function with this reference of an id.
So, I don't think it's actually doing anything special there because that's
just how it works in React now.
If you put an action here, and then you put some path to a server,
it's gonna go try to do that.
So, it might be doing something where it allows you
to handle a function here instead.
But I actually don't know because I've never used this before.
If action already allows you to do that.
So, could be, but I suspect that, if anything,
that would be React doing something and not Nextjs.
>> Learner: That sounds right, yeah.
>> Scott Moss: Yeah.
>> Learner: Gotcha, so maybe the next magic doesn't really work or
doesn't really do anything until you call the await sign up,
that's when Next starts to do their API stuff for you.
>> Scott Moss: Yeah, that's when Next creates that stuff for you.
And to be fair, Next is just like server actions is a React spec thing.
It has little to do with Nextjs.
It's just Nextjs implemented the part that goes across the network boundary for you,
but how it's supposed to work and the fact that it's compatible,
that's just React, Nextjs is like, we just implemented it.
We're just the thing in the middle, so it's all React.
Okay, if you try to run this, it's probably, well, I think if you,
which one's broken?
One of these is broken.
Let's go see something in here.
It's the, yeah, get user by email.
We can just go in here right quick and
just export a function that does nothing so it won't break.
Export const, get user by email.
This is inside of the /lib /D-A-L, dal.
Why is it called that?
We'll get there in a second, but just export that so
it doesn't break on the import, cool, okay.
So, now if you try to run this, we can try to run this and see what errors we get.
What is this?
User, yeah, cuz it doesn't get user by email, that's fine.
And then sign up, I think that signup uses it too, let's see, yeah.
So obviously, it's gonna be chalked because we haven't implemented this, but
I just want you to see the function being ran, so you can see what's going on here.