Enhancing Forms with React Server Components by Aurora Scharff | React and Chill Conference
Aug 6, 2025
In this talk, we explore the application of React Server Components (RSC) to elevate the functionality and efficiency of forms. We will touch upon the core principles of RSC and their specific benefits for form development, such as improved load times and streamlined server-side processing. Additionally, we’ll learn the latest advancements in React 19 and the introduction of multiple new hooks.
Attendees will gain insights into practical strategies for integrating RSC into forms, focusing on enhancing user experience and reducing front-end complexities.
🔗 Conference Website: 🔗 Conference Website: https://reactandchill.live
👋 Code of Conduct: https://reactandchill.live/code-of-co...
📺 CSharp TV - Dev Streaming Destination http://csharp.tv
🌎 C# Corner - Community of Software and Data Developers
https://www.c-sharpcorner.com
#CSharpTV #CSharpCorner #CSharp #dotNet #ReactAndChill
Show More Show Less View Video Transcript
0:03
so I'm going to be doing a session with
0:04
so I'm going to be doing a session with
0:04
so I'm going to be doing a session with mostly live coding today um with the
0:06
mostly live coding today um with the
0:06
mostly live coding today um with the goal of teaching how to work with forms
0:08
goal of teaching how to work with forms
0:08
goal of teaching how to work with forms and RC's in
0:10
and RC's in
0:10
and RC's in practice so first about me you saw that
0:13
practice so first about me you saw that
0:13
practice so first about me you saw that was a really nice intro intro there but
0:15
was a really nice intro intro there but
0:15
was a really nice intro intro there but I'm from Norway I work as a consultant
0:17
I'm from Norway I work as a consultant
0:17
I'm from Norway I work as a consultant at in meta and I work in AO and I'm
0:20
at in meta and I work in AO and I'm
0:20
at in meta and I work in AO and I'm mostly working with FB development and
0:22
mostly working with FB development and
0:22
mostly working with FB development and in my current project at my consultancy
0:24
in my current project at my consultancy
0:24
in my current project at my consultancy I am actively building with RC so I hope
0:27
I am actively building with RC so I hope
0:27
I am actively building with RC so I hope to share some of my experience here uh
0:28
to share some of my experience here uh
0:28
to share some of my experience here uh from that with you
0:31
from that with you
0:31
from that with you so let's begin by looking at this
0:32
so let's begin by looking at this
0:32
so let's begin by looking at this typical single page application it's
0:34
typical single page application it's
0:34
typical single page application it's great you have your react query your
0:36
great you have your react query your
0:36
great you have your react query your react form and all is well but as we
0:39
react form and all is well but as we
0:39
react form and all is well but as we know client ads have their
0:41
know client ads have their
0:41
know client ads have their problems so they run purely with
0:44
problems so they run purely with
0:44
problems so they run purely with JavaScript and the entire page or theab
0:46
JavaScript and the entire page or theab
0:46
JavaScript and the entire page or theab application is constructed from
0:48
application is constructed from
0:48
application is constructed from JavaScript when the user opens the URL
0:51
JavaScript when the user opens the URL
0:51
JavaScript when the user opens the URL if you're working for uh from a slow
0:53
if you're working for uh from a slow
0:53
if you're working for uh from a slow device or slow connection it can take a
0:55
device or slow connection it can take a
0:55
device or slow connection it can take a really long time to download and execute
0:58
really long time to download and execute
0:58
really long time to download and execute and uh uh part download person and
1:00
and uh uh part download person and
1:00
and uh uh part download person and execute all this JavaScript to even load
1:02
execute all this JavaScript to even load
1:02
execute all this JavaScript to even load the page to you know fill out a simple
1:04
the page to you know fill out a simple
1:04
the page to you know fill out a simple form something like that and in addition
1:06
form something like that and in addition
1:06
form something like that and in addition to submit data to a database you would
1:08
to submit data to a database you would
1:08
to submit data to a database you would want to need a backend because you can't
1:11
want to need a backend because you can't
1:11
want to need a backend because you can't rely only on the client
1:15
validation uh and even with a framework
1:17
validation uh and even with a framework
1:17
validation uh and even with a framework like next yes you might still have
1:19
like next yes you might still have
1:19
like next yes you might still have issues because even though you fix your
1:22
issues because even though you fix your
1:22
issues because even though you fix your problem uh of blank screens by randoming
1:24
problem uh of blank screens by randoming
1:24
problem uh of blank screens by randoming the pages you now have an even bigger
1:26
the pages you now have an even bigger
1:26
the pages you now have an even bigger dependency waterfall of uh downloading
1:29
dependency waterfall of uh downloading
1:29
dependency waterfall of uh downloading parsing executing the job JavaScript
1:30
parsing executing the job JavaScript
1:30
parsing executing the job JavaScript then hyding the hydrating the entire
1:33
then hyding the hydrating the entire
1:33
then hyding the hydrating the entire page before anything really
1:36
page before anything really
1:36
page before anything really works and let's not forget the struggles
1:38
works and let's not forget the struggles
1:38
works and let's not forget the struggles of working with form in the nextjs pages
1:40
of working with form in the nextjs pages
1:40
of working with form in the nextjs pages router so back then uh you had to
1:43
router so back then uh you had to
1:43
router so back then uh you had to manually create your own API endpoints
1:45
manually create your own API endpoints
1:45
manually create your own API endpoints every time you wanted to safely submit a
1:47
every time you wanted to safely submit a
1:47
every time you wanted to safely submit a form to the server you would want to use
1:49
form to the server you would want to use
1:50
form to the server you would want to use a library like trpc to ensure type
1:52
a library like trpc to ensure type
1:52
a library like trpc to ensure type safety you might have to write a bunch
1:55
safety you might have to write a bunch
1:55
safety you might have to write a bunch of excess messy code especially to
1:57
of excess messy code especially to
1:57
of excess messy code especially to handle errors and loading States so
2:00
handle errors and loading States so
2:00
handle errors and loading States so overall it was not a good developer
2:03
overall it was not a good developer
2:03
overall it was not a good developer experience so with the react server
2:05
experience so with the react server
2:05
experience so with the react server components uh which was announced as RC
2:08
components uh which was announced as RC
2:08
components uh which was announced as RC at react conf in may we now have server
2:10
at react conf in may we now have server
2:10
at react conf in may we now have server components react server components will
2:12
components react server components will
2:12
components react server components will run only on the server so therefore we
2:15
run only on the server so therefore we
2:15
run only on the server so therefore we can fetch data asynchronously inside
2:17
can fetch data asynchronously inside
2:17
can fetch data asynchronously inside components and access all our backend
2:20
components and access all our backend
2:20
components and access all our backend resources which will reduce the bundle
2:22
resources which will reduce the bundle
2:22
resources which will reduce the bundle size by minimizing the JavaScript sent
2:24
size by minimizing the JavaScript sent
2:24
size by minimizing the JavaScript sent to the client and then let us build
2:25
to the client and then let us build
2:25
to the client and then let us build performant apps with enjoyable
2:27
performant apps with enjoyable
2:27
performant apps with enjoyable developers experience
2:31
so what we want to do today is use react
2:34
so what we want to do today is use react
2:34
so what we want to do today is use react server components to write performant
2:36
server components to write performant
2:36
server components to write performant userfriendly forms without a lot of
2:37
userfriendly forms without a lot of
2:37
userfriendly forms without a lot of front and complexity we're going to need
2:40
front and complexity we're going to need
2:40
front and complexity we're going to need a framework uh to use RC's inside and
2:43
a framework uh to use RC's inside and
2:43
a framework uh to use RC's inside and nextjs with the app rouder is our pick
2:45
nextjs with the app rouder is our pick
2:46
nextjs with the app rouder is our pick here then we will be needing multiple
2:48
here then we will be needing multiple
2:48
here then we will be needing multiple other react 19 features that are already
2:50
other react 19 features that are already
2:50
other react 19 features that are already available in the app router which are
2:52
available in the app router which are
2:52
available in the app router which are server actions the form component use
2:55
server actions the form component use
2:55
server actions the form component use action State use form status and use
2:57
action State use form status and use
2:57
action State use form status and use optimistic
3:00
so server actions are defined with use
3:02
so server actions are defined with use
3:02
so server actions are defined with use server and tells the framework like
3:04
server and tells the framework like
3:04
server and tells the framework like nextjs to generate a post endpoint to a
3:07
nextjs to generate a post endpoint to a
3:07
nextjs to generate a post endpoint to a function that allows us to call it from
3:09
function that allows us to call it from
3:09
function that allows us to call it from any component for example from a client
3:12
any component for example from a client
3:12
any component for example from a client component it simplifies the
3:13
component it simplifies the
3:13
component it simplifies the communication across the server boundary
3:15
communication across the server boundary
3:15
communication across the server boundary while providing type safety with
3:19
while providing type safety with
3:19
while providing type safety with RPC the form component is reacts uh
3:22
RPC the form component is reacts uh
3:22
RPC the form component is reacts uh extension of the Native form component
3:25
extension of the Native form component
3:25
extension of the Native form component which now Builds on top of its existing
3:27
which now Builds on top of its existing
3:27
which now Builds on top of its existing methods the extension will let you
3:29
methods the extension will let you
3:29
methods the extension will let you create interactive controls um for
3:32
create interactive controls um for
3:32
create interactive controls um for submitting information for example by
3:34
submitting information for example by
3:34
submitting information for example by letting the action property now also
3:36
letting the action property now also
3:36
letting the action property now also call a function typically it could be a
3:39
call a function typically it could be a
3:39
call a function typically it could be a server action so the function you pass
3:42
server action so the function you pass
3:42
server action so the function you pass will automatically be wrapped in
3:43
will automatically be wrapped in
3:43
will automatically be wrapped in transition contain a hidden form data
3:45
transition contain a hidden form data
3:45
transition contain a hidden form data argument with the values of the form and
3:48
argument with the values of the form and
3:48
argument with the values of the form and in the case of a server action be called
3:50
in the case of a server action be called
3:50
in the case of a server action be called as a HTP
3:53
as a HTP
3:53
as a HTP post the Ed form status Hook is a hook
3:56
post the Ed form status Hook is a hook
3:56
post the Ed form status Hook is a hook that provides information about the last
3:57
that provides information about the last
3:57
that provides information about the last form submission it can be used in inside
3:59
form submission it can be used in inside
4:00
form submission it can be used in inside a form uh
4:01
a form uh
4:01
a form uh component um in a component inside a
4:04
component um in a component inside a
4:04
component um in a component inside a form and it can be used for example to
4:06
form and it can be used for example to
4:06
form and it can be used for example to display disable a button or display
4:09
display disable a button or display
4:09
display disable a button or display what's currently being
4:10
what's currently being
4:10
what's currently being submitted this hook enables progress
4:12
submitted this hook enables progress
4:12
submitted this hook enables progress enhancement because if the JavaScript
4:15
enhancement because if the JavaScript
4:15
enhancement because if the JavaScript has not hydrated the component it will
4:17
has not hydrated the component it will
4:17
has not hydrated the component it will still work it just won't display any uh
4:19
still work it just won't display any uh
4:19
still work it just won't display any uh pending feedback as we see in the the GI
4:23
pending feedback as we see in the the GI
4:23
pending feedback as we see in the the GI here use action state is another Hook
4:26
here use action state is another Hook
4:26
here use action state is another Hook from react 19 that allows you to update
4:28
from react 19 that allows you to update
4:28
from react 19 that allows you to update State based on the result of an action
4:31
State based on the result of an action
4:31
State based on the result of an action it also supports Progressive enhancement
4:33
it also supports Progressive enhancement
4:33
it also supports Progressive enhancement by allowing the server's response to be
4:35
by allowing the server's response to be
4:35
by allowing the server's response to be shown without JavaScript before
4:37
shown without JavaScript before
4:37
shown without JavaScript before hydration has completed this hook can be
4:39
hydration has completed this hook can be
4:39
hydration has completed this hook can be used for example to display air messages
4:41
used for example to display air messages
4:41
used for example to display air messages or other information that is based on
4:43
or other information that is based on
4:43
or other information that is based on the return value of the
4:46
the return value of the
4:46
the return value of the action and the final Hook is use
4:48
action and the final Hook is use
4:48
action and the final Hook is use optimistic which lets you optimistically
4:50
optimistic which lets you optimistically
4:50
optimistic which lets you optimistically update UI while a background operation
4:53
update UI while a background operation
4:53
update UI while a background operation completes it lets you keep the UI Snappy
4:55
completes it lets you keep the UI Snappy
4:55
completes it lets you keep the UI Snappy by providing instant feedback to
4:58
by providing instant feedback to
4:58
by providing instant feedback to interactions and you can use it with
5:00
interactions and you can use it with
5:00
interactions and you can use it with server actions and form submissions but
5:02
server actions and form submissions but
5:02
server actions and form submissions but it can also be used with other
5:04
it can also be used with other
5:04
it can also be used with other potentially slow operations such as
5:05
potentially slow operations such as
5:05
potentially slow operations such as filtering based on Route
5:07
filtering based on Route
5:07
filtering based on Route progams and it stands out because of its
5:10
progams and it stands out because of its
5:10
progams and it stands out because of its ability to seamlessly merge the client
5:12
ability to seamlessly merge the client
5:12
ability to seamlessly merge the client and the service state as the server
5:13
and the service state as the server
5:13
and the service state as the server finishes its
5:16
update okay so with that in mind let's
5:19
update okay so with that in mind let's
5:19
update okay so with that in mind let's move on to the demo I'm going to be
5:21
move on to the demo I'm going to be
5:21
move on to the demo I'm going to be coding a simplified version of something
5:23
coding a simplified version of something
5:23
coding a simplified version of something that I've made for my current
5:25
that I've made for my current
5:25
that I've made for my current consultancy project where we use
5:27
consultancy project where we use
5:27
consultancy project where we use RC so let me just jump over to uh my
5:31
RC so let me just jump over to uh my
5:31
RC so let me just jump over to uh my code
5:32
code
5:32
code here ah I need to reopen something here
5:35
here ah I need to reopen something here
5:35
here ah I need to reopen something here because it closed when I reset my um
5:38
because it closed when I reset my um
5:38
because it closed when I reset my um hold on one second
5:40
hold on one second
5:40
hold on one second here and we're here
5:44
here and we're here
5:44
here and we're here and we're going to go to Local Host
5:48
here
5:51
here
5:51
here um
5:54
um
5:54
um 3,000 there we
5:57
3,000 there we
5:57
3,000 there we go um
6:01
okay so I'm here in the nextjs app
6:05
okay so I'm here in the nextjs app
6:05
okay so I'm here in the nextjs app router and I'm using Prisma as my orm
6:08
router and I'm using Prisma as my orm
6:08
router and I'm using Prisma as my orm and I have a local database and I have
6:10
and I have a local database and I have
6:10
and I have a local database and I have Tailwind for
6:11
Tailwind for
6:11
Tailwind for CSS so since we're in the app rou
6:13
CSS so since we're in the app rou
6:13
CSS so since we're in the app rou everything is a server component by
6:15
everything is a server component by
6:15
everything is a server component by default and uh this is all server
6:17
default and uh this is all server
6:17
default and uh this is all server components here for this message
6:20
components here for this message
6:20
components here for this message box so the message message box component
6:23
box so the message message box component
6:23
box so the message message box component is a server component it can be async
6:26
is a server component it can be async
6:26
is a server component it can be async and it can
6:27
and it can
6:27
and it can asly uh fetch message from our database
6:31
asly uh fetch message from our database
6:31
asly uh fetch message from our database using
6:33
Prisma and then it's um doing some nice
6:36
Prisma and then it's um doing some nice
6:36
Prisma and then it's um doing some nice styling and then mapping each message to
6:39
styling and then mapping each message to
6:39
styling and then mapping each message to individual message display
6:41
individual message display
6:41
individual message display components and this is also just uh
6:43
components and this is also just uh
6:43
components and this is also just uh styling based on whether the user is the
6:45
styling based on whether the user is the
6:45
styling based on whether the user is the one who has written the message or not
6:48
one who has written the message or not
6:48
one who has written the message or not and this is also just the server
6:50
and this is also just the server
6:50
and this is also just the server component and finally the message input
6:54
component and finally the message input
6:54
component and finally the message input uh another server component which is not
6:56
uh another server component which is not
6:57
uh another server component which is not really doing anything right now I can
6:59
really doing anything right now I can
6:59
really doing anything right now I can try out nothing's happening here it's
7:02
try out nothing's happening here it's
7:02
try out nothing's happening here it's just an
7:04
just an
7:04
just an input so um what we want to do here is
7:07
input so um what we want to do here is
7:07
input so um what we want to do here is enhance this message box with react
7:09
enhance this message box with react
7:09
enhance this message box with react server components and react 19 where the
7:12
server components and react 19 where the
7:12
server components and react 19 where the goal will be to make this interactive
7:14
goal will be to make this interactive
7:14
goal will be to make this interactive while minimizing the js on the client
7:16
while minimizing the js on the client
7:16
while minimizing the js on the client and reducing the fronting
7:23
complexity so let's begin by making this
7:25
complexity so let's begin by making this
7:25
complexity so let's begin by making this form
7:27
form
7:27
form work so we're going to use react
7:29
work so we're going to use react
7:29
work so we're going to use react extension of the form component to bind
7:31
extension of the form component to bind
7:31
extension of the form component to bind this action property to a function we're
7:34
this action property to a function we're
7:34
this action property to a function we're going to call it submit
7:37
going to call it submit
7:37
going to call it submit message and it's going to be a server
7:39
message and it's going to be a server
7:39
message and it's going to be a server action so I'm going to make it inside my
7:41
action so I'm going to make it inside my
7:41
action so I'm going to make it inside my actions uh lip dat access layer
7:44
actions uh lip dat access layer
7:44
actions uh lip dat access layer here and we're going to use a server
7:47
here and we're going to use a server
7:47
here and we're going to use a server action here so we're going to say use
7:48
action here so we're going to say use
7:48
action here so we're going to say use server which means that the content of
7:51
server which means that the content of
7:51
server which means that the content of this file will uh the functions in this
7:53
this file will uh the functions in this
7:53
this file will uh the functions in this file will have a hidden post endpoint
7:55
file will have a hidden post endpoint
7:55
file will have a hidden post endpoint generated and we can call them from
7:57
generated and we can call them from
7:57
generated and we can call them from anywhere
7:59
anywhere
7:59
anywhere and we're going to export an Asing
8:02
and we're going to export an Asing
8:02
and we're going to export an Asing function called submit message which
8:05
function called submit message which
8:05
function called submit message which takes in a form data uh argument of type
8:08
takes in a form data uh argument of type
8:08
takes in a form data uh argument of type form data and what this means is that
8:11
form data and what this means is that
8:11
form data and what this means is that each field in this form will be
8:13
each field in this form will be
8:13
each field in this form will be submitted with its value inside the form
8:15
submitted with its value inside the form
8:15
submitted with its value inside the form data object on
8:18
data object on
8:18
data object on submission and we can use this to um
8:21
submission and we can use this to um
8:21
submission and we can use this to um insert into our database with Prisma
8:24
insert into our database with Prisma
8:24
insert into our database with Prisma going to create a message where the data
8:26
going to create a message where the data
8:26
going to create a message where the data will
8:27
will
8:27
will be the content will be uh from the form
8:32
be the content will be uh from the form
8:32
be the content will be uh from the form data and we also need a user ID
8:36
data and we also need a user ID
8:36
data and we also need a user ID here uh sorry created by
8:39
here uh sorry created by
8:39
here uh sorry created by ID and I'm just going to close this up
8:43
ID and I'm just going to close this up
8:43
ID and I'm just going to close this up so somehow we need to pass an additional
8:45
so somehow we need to pass an additional
8:45
so somehow we need to pass an additional argument to our uh function and you can
8:49
argument to our uh function and you can
8:49
argument to our uh function and you can do this in a couple ways you can use a
8:51
do this in a couple ways you can use a
8:51
do this in a couple ways you can use a bind or just pass it inside the formul
8:53
bind or just pass it inside the formul
8:53
bind or just pass it inside the formul down so I'm going to do a hidden
8:57
down so I'm going to do a hidden
8:57
down so I'm going to do a hidden input um to pass the user ID inside the
9:00
input um to pass the user ID inside the
9:00
input um to pass the user ID inside the form data object and I'll import the
9:02
form data object and I'll import the
9:02
form data object and I'll import the function and remove this console
9:04
function and remove this console
9:04
function and remove this console log and it's worth noting that in the
9:08
log and it's worth noting that in the
9:08
log and it's worth noting that in the real world you probably don't want to
9:09
real world you probably don't want to
9:09
real world you probably don't want to pass your user ID uh from the client
9:12
pass your user ID uh from the client
9:12
pass your user ID uh from the client like this but this is just an example uh
9:13
like this but this is just an example uh
9:13
like this but this is just an example uh to show how you can pass additional
9:16
to show how you can pass additional
9:16
to show how you can pass additional arguments so let's try it out just like
9:18
arguments so let's try it out just like
9:18
arguments so let's try it out just like that I'm going to say hey and manually
9:22
that I'm going to say hey and manually
9:22
that I'm going to say hey and manually refresh the page and it's been
9:24
refresh the page and it's been
9:24
refresh the page and it's been submitted so it's just like that
9:26
submitted so it's just like that
9:26
submitted so it's just like that manipulated my database but I don't want
9:29
manipulated my database but I don't want
9:29
manipulated my database but I don't want to refresh the page manually of course
9:32
to refresh the page manually of course
9:32
to refresh the page manually of course so I'm going to use the next year's API
9:34
so I'm going to use the next year's API
9:34
so I'm going to use the next year's API revalidate path with the root path which
9:38
revalidate path with the root path which
9:38
revalidate path with the root path which means that I'm telling next yours to
9:39
means that I'm telling next yours to
9:39
means that I'm telling next yours to purch the server component cache and
9:41
purch the server component cache and
9:41
purch the server component cache and regenerate uh whatever is on this path
9:45
regenerate uh whatever is on this path
9:45
regenerate uh whatever is on this path so now I can say hi and it's been
9:47
so now I can say hi and it's been
9:47
so now I can say hi and it's been submitted without a hard refresh
9:51
submitted without a hard refresh
9:51
submitted without a hard refresh there now when I submit my message I'm
9:55
there now when I submit my message I'm
9:55
there now when I submit my message I'm still um in this scroll position where I
9:57
still um in this scroll position where I
9:57
still um in this scroll position where I don't see the new message so it would be
10:00
don't see the new message so it would be
10:00
don't see the new message so it would be nice if I can make it interactive by
10:01
nice if I can make it interactive by
10:01
nice if I can make it interactive by automatically scrolling to the bottom
10:03
automatically scrolling to the bottom
10:03
automatically scrolling to the bottom when there is a new
10:05
when there is a new
10:05
when there is a new message so I'm going to head over to the
10:07
message so I'm going to head over to the
10:07
message so I'm going to head over to the message box
10:08
message box
10:08
message box component and I'm just going to change
10:11
component and I'm just going to change
10:11
component and I'm just going to change this div into an automatic
10:15
scroller and this component uh is a
10:18
scroller and this component uh is a
10:18
scroller and this component uh is a client component because it's using an
10:20
client component because it's using an
10:20
client component because it's using an effect and a mutation Observer to uh
10:23
effect and a mutation Observer to uh
10:23
effect and a mutation Observer to uh listen for a new child in the container
10:27
listen for a new child in the container
10:27
listen for a new child in the container and scroll to the bottom and this this
10:29
and scroll to the bottom and this this
10:29
and scroll to the bottom and this this requires JavaScript obviously um so it's
10:32
requires JavaScript obviously um so it's
10:32
requires JavaScript obviously um so it's a client component but since I'm
10:34
a client component but since I'm
10:34
a client component but since I'm wrapping it like this around server
10:36
wrapping it like this around server
10:36
wrapping it like this around server content using the children property I do
10:39
content using the children property I do
10:39
content using the children property I do not convert the content uh into client
10:42
not convert the content uh into client
10:42
not convert the content uh into client as
10:43
as
10:43
as well and we can uh prove that by looking
10:46
well and we can uh prove that by looking
10:46
well and we can uh prove that by looking inside the react Dev
10:48
inside the react Dev
10:48
inside the react Dev tools and see that there is an automatic
10:52
tools and see that there is an automatic
10:52
tools and see that there is an automatic scroller in the component Tre but there
10:54
scroller in the component Tre but there
10:54
scroller in the component Tre but there is no message display because only the
10:56
is no message display because only the
10:56
is no message display because only the automatic scroller has been shipped to
10:58
automatic scroller has been shipped to
10:58
automatic scroller has been shipped to the client as a component
10:59
the client as a component
10:59
the client as a component and has
11:02
and has
11:02
and has JavaScript and let's see what it looks
11:04
JavaScript and let's see what it looks
11:04
JavaScript and let's see what it looks like now when we add a new message can
11:07
like now when we add a new message can
11:07
like now when we add a new message can say hi and it's now scrolling to the
11:09
say hi and it's now scrolling to the
11:09
say hi and it's now scrolling to the bottom uh with this interactive uh
11:12
bottom uh with this interactive uh
11:12
bottom uh with this interactive uh scroller
11:15
here so the next thing we should do is
11:18
here so the next thing we should do is
11:18
here so the next thing we should do is validate our data because form data it's
11:20
validate our data because form data it's
11:20
validate our data because form data it's from the client it's uh we doesn't we
11:22
from the client it's uh we doesn't we
11:22
from the client it's uh we doesn't we don't really know anything about
11:24
don't really know anything about
11:24
don't really know anything about it so we're going to get a result from a
11:28
it so we're going to get a result from a
11:29
it so we're going to get a result from a uh from a message schema which is a
11:31
uh from a message schema which is a
11:31
uh from a message schema which is a schema defined with sad which will at
11:34
schema defined with sad which will at
11:34
schema defined with sad which will at runtime validate or um validate whatever
11:38
runtime validate or um validate whatever
11:38
runtime validate or um validate whatever it's being U gets passed in to make sure
11:40
it's being U gets passed in to make sure
11:40
it's being U gets passed in to make sure that the content is at least one
11:42
that the content is at least one
11:42
that the content is at least one character and that the created by ID is
11:46
character and that the created by ID is
11:46
character and that the created by ID is a uh um unique
11:49
a uh um unique
11:49
a uh um unique ID so we're going to safely parse um
11:54
ID so we're going to safely parse um
11:54
ID so we're going to safely parse um this object here that we were already
11:56
this object here that we were already
11:56
this object here that we were already using
11:59
using
11:59
using and use
12:01
and use
12:01
and use that to um mutate
12:06
that to um mutate
12:06
that to um mutate our and um we don't need to type these
12:10
our and um we don't need to type these
12:10
our and um we don't need to type these as strings because we're going to make
12:11
as strings because we're going to make
12:12
as strings because we're going to make sure that they turn into Strings when
12:13
sure that they turn into Strings when
12:13
sure that they turn into Strings when we're done with this
12:14
we're done with this
12:14
we're done with this validation and then we need to handle
12:17
validation and then we need to handle
12:17
validation and then we need to handle the case where this failed so if the
12:19
the case where this failed so if the
12:19
the case where this failed so if the result is not a success we can throw an
12:21
result is not a success we can throw an
12:21
result is not a success we can throw an error and say um invalid message data
12:24
error and say um invalid message data
12:24
error and say um invalid message data something like
12:26
something like
12:26
something like that so um now if I comment out my
12:30
that so um now if I comment out my
12:30
that so um now if I comment out my client side valid validation and try to
12:32
client side valid validation and try to
12:32
client side valid validation and try to submit in a message invalid message I
12:35
submit in a message invalid message I
12:35
submit in a message invalid message I will get an error here because it didn't
12:36
will get an error here because it didn't
12:36
will get an error here because it didn't pass the
12:38
pass the
12:38
pass the validation and you can do whatever you
12:40
validation and you can do whatever you
12:40
validation and you can do whatever you want with your errors but uh a way to do
12:43
want with your errors but uh a way to do
12:43
want with your errors but uh a way to do it is by using an error
12:45
it is by using an error
12:45
it is by using an error boundary so I'm going to make an error
12:48
boundary so I'm going to make an error
12:48
boundary so I'm going to make an error boundary around this message
12:51
boundary around this message
12:51
boundary around this message input um and see how it looks now so if
12:56
input um and see how it looks now so if
12:56
input um and see how it looks now so if it's invalid the airror boundary will
12:58
it's invalid the airror boundary will
12:58
it's invalid the airror boundary will catch my error and U make sure that the
13:01
catch my error and U make sure that the
13:01
catch my error and U make sure that the whole app doesn't
13:03
whole app doesn't
13:03
whole app doesn't break uh so let me just put back this
13:05
break uh so let me just put back this
13:05
break uh so let me just put back this client side
13:07
client side
13:07
client side validation and get back to the submit
13:10
validation and get back to the submit
13:10
validation and get back to the submit message because maybe I don't want to
13:13
message because maybe I don't want to
13:13
message because maybe I don't want to throw an error it's just a validation
13:15
throw an error it's just a validation
13:15
throw an error it's just a validation error maybe I would rather return
13:17
error maybe I would rather return
13:17
error maybe I would rather return something so what I will do is I will
13:20
something so what I will do is I will
13:20
something so what I will do is I will return a Suess
13:22
return a Suess
13:22
return a Suess false and I'm going to return a
13:24
false and I'm going to return a
13:24
false and I'm going to return a timestamp and we're going to use Slater
13:26
timestamp and we're going to use Slater
13:26
timestamp and we're going to use Slater I'm just going to create it now
13:28
I'm just going to create it now
13:28
I'm just going to create it now timestamp
13:30
timestamp
13:30
timestamp H that's okay just like
13:33
that and I also need to return an error
13:37
that and I also need to return an error
13:37
that and I also need to return an error we can just say again invalid message
13:41
we can just say again invalid message
13:41
we can just say again invalid message data something like
13:44
that and then um maybe you want to do
13:47
that and then um maybe you want to do
13:47
that and then um maybe you want to do something else in on the server here
13:49
something else in on the server here
13:49
something else in on the server here maybe check that user exists could be
13:51
maybe check that user exists could be
13:51
maybe check that user exists could be anything in my case I'm going to limit
13:54
anything in my case I'm going to limit
13:54
anything in my case I'm going to limit the amount of messages the user can
13:56
the amount of messages the user can
13:56
the amount of messages the user can send so if uh actually we're going to
14:00
send so if uh actually we're going to
14:01
send so if uh actually we're going to get messages for a
14:03
get messages for a
14:03
get messages for a user and say await get
14:07
user and say await get
14:07
user and say await get messages for the user uh created by ID
14:10
messages for the user uh created by ID
14:10
messages for the user uh created by ID here and if it's bigger or if there's
14:13
here and if it's bigger or if there's
14:13
here and if it's bigger or if there's more messages than let's say five we can
14:16
more messages than let's say five we can
14:16
more messages than let's say five we can say user has to reach the maximum number
14:17
say user has to reach the maximum number
14:17
say user has to reach the maximum number of messages success fs and return also
14:20
of messages success fs and return also
14:20
of messages success fs and return also the time
14:21
the time
14:21
the time stamp and if all as well we can insert
14:24
stamp and if all as well we can insert
14:24
stamp and if all as well we can insert into the database Ral dat the path and
14:26
into the database Ral dat the path and
14:26
into the database Ral dat the path and then finally return success true
14:30
then finally return success true
14:30
then finally return success true and if for some reason something goes
14:31
and if for some reason something goes
14:32
and if for some reason something goes wrong in this um
14:34
wrong in this um
14:34
wrong in this um Prisma uh query here I can just let my
14:37
Prisma uh query here I can just let my
14:37
Prisma uh query here I can just let my air B boundary handle that
14:40
air B boundary handle that
14:40
air B boundary handle that problem so I have a lot of uh server
14:43
problem so I have a lot of uh server
14:43
problem so I have a lot of uh server side logic now I need to return this to
14:46
side logic now I need to return this to
14:46
side logic now I need to return this to the user
14:48
the user
14:48
the user somehow so I'm going to use one of the
14:51
somehow so I'm going to use one of the
14:51
somehow so I'm going to use one of the new react 19 hooks called use action
14:54
new react 19 hooks called use action
14:55
new react 19 hooks called use action State and it will return first let's
14:58
State and it will return first let's
14:58
State and it will return first let's make this
15:00
make this
15:00
make this uh it will take in a function to call on
15:03
uh it will take in a function to call on
15:03
uh it will take in a function to call on um Trigger or when it when the hook is
15:07
um Trigger or when it when the hook is
15:07
um Trigger or when it when the hook is being called and an initial State and
15:11
being called and an initial State and
15:11
being called and an initial State and the initial State can just be success
15:14
the initial State can just be success
15:14
the initial State can just be success false and it will
15:17
false and it will
15:17
false and it will return uh a generated component state
15:20
return uh a generated component state
15:20
return uh a generated component state which is equal to First the initial
15:22
which is equal to First the initial
15:22
which is equal to First the initial State and then after that the last
15:24
State and then after that the last
15:24
State and then after that the last return value of the action that use
15:26
return value of the action that use
15:26
return value of the action that use action status
15:27
action status
15:27
action status wrapping and it also returns returns a
15:31
wrapping and it also returns returns a
15:31
wrapping and it also returns returns a um a WRA action to calls which is going
15:33
um a WRA action to calls which is going
15:33
um a WRA action to calls which is going to call be called submit message action
15:35
to call be called submit message action
15:35
to call be called submit message action by convention
15:37
by convention
15:37
by convention here and I can use this to replace on my
15:40
here and I can use this to replace on my
15:40
here and I can use this to replace on my form action property and I can use the
15:43
form action property and I can use the
15:43
form action property and I can use the state to display an error message
15:49
here should be erir excuse me this
15:51
here should be erir excuse me this
15:51
here should be erir excuse me this should be erir over
15:53
should be erir over
15:53
should be erir over here like that now I'm getting the error
15:56
here like that now I'm getting the error
15:56
here like that now I'm getting the error from the from the action
15:59
from the from the action
15:59
from the from the action and there's a couple things I need to
16:01
and there's a couple things I need to
16:01
and there's a couple things I need to fix now first use action state is a hook
16:04
fix now first use action state is a hook
16:04
fix now first use action state is a hook I need to tell the bundler to load the
16:06
I need to tell the bundler to load the
16:06
I need to tell the bundler to load the JavaScript for this component with use
16:10
JavaScript for this component with use
16:10
JavaScript for this component with use client and I need to update my function
16:12
client and I need to update my function
16:13
client and I need to update my function that I'm passing here because use action
16:14
that I'm passing here because use action
16:14
that I'm passing here because use action State also passes a previous state
16:17
State also passes a previous state
16:17
State also passes a previous state argument to the function which I'm just
16:20
argument to the function which I'm just
16:20
argument to the function which I'm just going to say PR state I'm not going to
16:22
going to say PR state I'm not going to
16:22
going to say PR state I'm not going to use it now but we need to put it
16:24
use it now but we need to put it
16:24
use it now but we need to put it there and I'm just going to say message
16:27
there and I'm just going to say message
16:27
there and I'm just going to say message State here so we don't don't have to
16:29
State here so we don't don't have to
16:29
State here so we don't don't have to write types in this talk and all is good
16:34
write types in this talk and all is good
16:34
write types in this talk and all is good now so let's see what happens and I say
16:39
now so let's see what happens and I say
16:39
now so let's see what happens and I say hey and then
16:41
hey and then
16:41
hey and then hi and now I hit my Max message count
16:44
hi and now I hit my Max message count
16:44
hi and now I hit my Max message count and I will get the return value of the
16:47
and I will get the return value of the
16:47
and I will get the return value of the submit message uh function to my
16:50
submit message uh function to my
16:50
submit message uh function to my component
16:53
here and uh you could check for anything
16:56
here and uh you could check for anything
16:56
here and uh you could check for anything when you're when you're doing um return
16:59
when you're when you're doing um return
16:59
when you're when you're doing um return something you can maybe return each
17:01
something you can maybe return each
17:01
something you can maybe return each error value for the form Fields but I
17:03
error value for the form Fields but I
17:03
error value for the form Fields but I just have one uh form field here so it's
17:05
just have one uh form field here so it's
17:05
just have one uh form field here so it's not really relevant in my case but you
17:06
not really relevant in my case but you
17:06
not really relevant in my case but you could do
17:08
could do
17:08
could do that the next thing that I want to
17:10
that the next thing that I want to
17:10
that the next thing that I want to improve is make it feel a little bit
17:13
improve is make it feel a little bit
17:13
improve is make it feel a little bit more
17:14
more
17:14
more interative with this error message that
17:16
interative with this error message that
17:16
interative with this error message that I'm getting so I'm going to use an
17:20
I'm getting so I'm going to use an
17:20
I'm getting so I'm going to use an effect um to check if this state has an
17:24
effect um to check if this state has an
17:24
effect um to check if this state has an error and if it does I can just toast an
17:27
error and if it does I can just toast an
17:28
error and if it does I can just toast an error with that
17:29
error with that
17:29
error with that there and uh it's going to need a
17:31
there and uh it's going to need a
17:32
there and uh it's going to need a dependency array which is going to be
17:33
dependency array which is going to be
17:33
dependency array which is going to be the aor but also this time stamp that we
17:36
the aor but also this time stamp that we
17:36
the aor but also this time stamp that we created so that every time the time step
17:37
created so that every time the time step
17:37
created so that every time the time step changes we get a new
17:40
changes we get a new
17:40
changes we get a new toast so now when we get an error we're
17:43
toast so now when we get an error we're
17:43
toast so now when we get an error we're going to get also this toast
17:46
going to get also this toast
17:46
going to get also this toast here which means I don't need my error
17:49
here which means I don't need my error
17:49
here which means I don't need my error message at the bottom here anymore but
17:51
message at the bottom here anymore but
17:51
message at the bottom here anymore but instead of removing it I'm just going to
17:53
instead of removing it I'm just going to
17:53
instead of removing it I'm just going to leave it as a no script fallback which
17:56
leave it as a no script fallback which
17:56
leave it as a no script fallback which means that for some reason if there's no
17:57
means that for some reason if there's no
17:57
means that for some reason if there's no JavaScript you will still be able to see
18:00
JavaScript you will still be able to see
18:00
JavaScript you will still be able to see this
18:04
error
18:07
error
18:07
error um uh let's try fixing something else so
18:11
um uh let's try fixing something else so
18:11
um uh let's try fixing something else so when I submit uh and I hit this Max
18:14
when I submit uh and I hit this Max
18:14
when I submit uh and I hit this Max message count my form field has been
18:16
message count my form field has been
18:16
message count my form field has been cleared and the reason for that is
18:19
cleared and the reason for that is
18:19
cleared and the reason for that is because when you use react 19 form
18:21
because when you use react 19 form
18:21
because when you use react 19 form actions with uncontrolled inputs it will
18:24
actions with uncontrolled inputs it will
18:24
actions with uncontrolled inputs it will automatically reset the form for you
18:26
automatically reset the form for you
18:26
automatically reset the form for you when the action completes which is a
18:29
when the action completes which is a
18:29
when the action completes which is a good thing because it kind of mimics
18:30
good thing because it kind of mimics
18:30
good thing because it kind of mimics this NPA form submission behavior that
18:32
this NPA form submission behavior that
18:32
this NPA form submission behavior that we're used to in the more um old ways of
18:34
we're used to in the more um old ways of
18:34
we're used to in the more um old ways of writing forms with the
18:36
writing forms with the
18:36
writing forms with the web but uh in this case I want to leave
18:40
web but uh in this case I want to leave
18:40
web but uh in this case I want to leave it there because maybe if my form had
18:42
it there because maybe if my form had
18:42
it there because maybe if my form had been different the user would have been
18:43
been different the user would have been
18:43
been different the user would have been able to change this input or this value
18:45
able to change this input or this value
18:45
able to change this input or this value inside the input to something that would
18:47
inside the input to something that would
18:47
inside the input to something that would be valid and would submit and I don't
18:49
be valid and would submit and I don't
18:49
be valid and would submit and I don't want them to rewrite whatever they just
18:52
want them to rewrite whatever they just
18:52
want them to rewrite whatever they just wrote so what I'm going to do is when
18:56
wrote so what I'm going to do is when
18:56
wrote so what I'm going to do is when this error occurs I'm going to also
18:58
this error occurs I'm going to also
18:58
this error occurs I'm going to also return return the
19:00
return return the
19:00
return return the content and what I will do is use this
19:03
content and what I will do is use this
19:03
content and what I will do is use this as the default value of the
19:07
as the default value of the
19:07
as the default value of the form and maybe if you've been working
19:09
form and maybe if you've been working
19:09
form and maybe if you've been working with reactor form you used to making
19:11
with reactor form you used to making
19:11
with reactor form you used to making this controlled form State well this is
19:13
this controlled form State well this is
19:13
this controlled form State well this is just uncontrolled inputs and default
19:16
just uncontrolled inputs and default
19:16
just uncontrolled inputs and default value and now if I try to type something
19:20
value and now if I try to type something
19:20
value and now if I try to type something it will not reset my form or the default
19:22
it will not reset my form or the default
19:22
it will not reset my form or the default Val value will be the return value of
19:24
Val value will be the return value of
19:24
Val value will be the return value of this
19:27
data um um but what if the trip to the
19:31
data um um but what if the trip to the
19:31
data um um but what if the trip to the server back back is a bit
19:35
server back back is a bit
19:35
server back back is a bit slow so that's realistic because I'm
19:37
slow so that's realistic because I'm
19:37
slow so that's realistic because I'm just using a local database here it will
19:40
just using a local database here it will
19:40
just using a local database here it will take a bit of some time here for me to
19:43
take a bit of some time here for me to
19:43
take a bit of some time here for me to see uh the
19:45
see uh the
19:45
see uh the response and maybe I would be
19:47
response and maybe I would be
19:47
response and maybe I would be accidentally submitting more messages so
19:49
accidentally submitting more messages so
19:49
accidentally submitting more messages so I need to uh handle that
19:52
I need to uh handle that
19:52
I need to uh handle that somehow and the use action State
19:54
somehow and the use action State
19:54
somehow and the use action State actually returns a third argument is
19:57
actually returns a third argument is
19:57
actually returns a third argument is pending or return third
20:00
pending or return third
20:00
pending or return third value which I can use um to disable my
20:06
value which I can use um to disable my
20:06
value which I can use um to disable my button and say something else here
20:09
button and say something else here
20:09
button and say something else here like uh
20:13
sending
20:17
um what happened here let's try this
20:20
um what happened here let's try this
20:21
um what happened here let's try this again like that so now when it's being
20:24
again like that so now when it's being
20:24
again like that so now when it's being slow I will see that it's sending and I
20:27
slow I will see that it's sending and I
20:27
slow I will see that it's sending and I won't be able to click again
20:31
so um let's just increase this Max
20:35
so um let's just increase this Max
20:35
so um let's just increase this Max message count to eight and see the full
20:37
message count to eight and see the full
20:37
message count to eight and see the full interactive message box
20:39
interactive message box
20:39
interactive message box again so I'm going to just open this up
20:42
again so I'm going to just open this up
20:42
again so I'm going to just open this up and say hey and we'll see the sending
20:45
and say hey and we'll see the sending
20:45
and say hey and we'll see the sending the automatic scroll and the field form
20:48
the automatic scroll and the field form
20:48
the automatic scroll and the field form reset and this is just so much easier to
20:50
reset and this is just so much easier to
20:50
reset and this is just so much easier to handle than the pag rer uh form
20:53
handle than the pag rer uh form
20:53
handle than the pag rer uh form submission but uh what's good here is
20:56
submission but uh what's good here is
20:57
submission but uh what's good here is this whole form will actually work
20:58
this whole form will actually work
20:58
this whole form will actually work without JavaScript so let me just
21:00
without JavaScript so let me just
21:00
without JavaScript so let me just disable the JavaScript to see
21:03
disable the JavaScript to see
21:03
disable the JavaScript to see that so I will say no
21:07
JavaScript and uh it worked I didn't get
21:11
JavaScript and uh it worked I didn't get
21:11
JavaScript and uh it worked I didn't get any automa scrolling I
21:13
any automa scrolling I
21:13
any automa scrolling I um and um I didn't get any pending state
21:16
um and um I didn't get any pending state
21:16
um and um I didn't get any pending state but everything still
21:18
but everything still
21:18
but everything still worked say no
21:20
worked say no
21:20
worked say no JS it's working still no
21:24
JS it's working still no
21:24
JS it's working still no JS and then I hit my Max message count
21:27
JS and then I hit my Max message count
21:27
JS and then I hit my Max message count and see this no script fall
21:30
and see this no script fall
21:30
and see this no script fall back so I'm just going to turn this back
21:33
back so I'm just going to turn this back
21:33
back so I'm just going to turn this back on and refresh
21:35
on and refresh
21:35
on and refresh here and go back to my uh initial
21:40
here and go back to my uh initial
21:40
here and go back to my uh initial view so what we've essentially been
21:42
view so what we've essentially been
21:42
view so what we've essentially been doing here is progressively enhancing
21:44
doing here is progressively enhancing
21:44
doing here is progressively enhancing this form meaning ensuring all the basic
21:47
this form meaning ensuring all the basic
21:47
this form meaning ensuring all the basic functionality works at the lowest level
21:48
functionality works at the lowest level
21:48
functionality works at the lowest level of resources and then which is no
21:51
of resources and then which is no
21:51
of resources and then which is no JavaScript and then adding things on top
21:53
JavaScript and then adding things on top
21:53
JavaScript and then adding things on top to enhance the user experience for users
21:55
to enhance the user experience for users
21:55
to enhance the user experience for users with those resources available so even
21:57
with those resources available so even
21:57
with those resources available so even if your users on a slow device or a slow
21:59
if your users on a slow device or a slow
21:59
if your users on a slow device or a slow connection they don't have to wait for
22:01
connection they don't have to wait for
22:01
connection they don't have to wait for JS to download parts and execute they
22:04
JS to download parts and execute they
22:04
JS to download parts and execute they can use the form while the page is still
22:06
can use the form while the page is still
22:06
can use the form while the page is still hydrating and since we reduce the js on
22:09
hydrating and since we reduce the js on
22:09
hydrating and since we reduce the js on the client with uh by limiting the JS in
22:11
the client with uh by limiting the JS in
22:11
the client with uh by limiting the JS in this automatic scroller the JS that we
22:14
this automatic scroller the JS that we
22:14
this automatic scroller the JS that we do want will load a lot
22:18
faster um there is however one more
22:20
faster um there is however one more
22:21
faster um there is however one more Improvement that I can make to this code
22:23
Improvement that I can make to this code
22:23
Improvement that I can make to this code so what I can do is I can extract this
22:26
so what I can do is I can extract this
22:26
so what I can do is I can extract this button into a submit button
22:31
so I want this to be a um composable and
22:34
so I want this to be a um composable and
22:34
so I want this to be a um composable and reusable way to get penden dat of a form
22:37
reusable way to get penden dat of a form
22:37
reusable way to get penden dat of a form going to say send here and I'm going to
22:39
going to say send here and I'm going to
22:39
going to say send here and I'm going to make it inside my UI UI
22:43
components and I'm just going to paste
22:46
components and I'm just going to paste
22:46
components and I'm just going to paste whatever was there inside
22:48
whatever was there inside
22:48
whatever was there inside here um and I need to get this pending
22:52
here um and I need to get this pending
22:52
here um and I need to get this pending state from somewhere so I'm going to use
22:55
state from somewhere so I'm going to use
22:55
state from somewhere so I'm going to use the new hook use form status
23:01
and it will return a couple of things
23:02
and it will return a couple of things
23:02
and it will return a couple of things you will get some data you will get a
23:04
you will get some data you will get a
23:04
you will get some data you will get a pending and a couple other things but we
23:06
pending and a couple other things but we
23:06
pending and a couple other things but we only need the pending here so I'm going
23:08
only need the pending here so I'm going
23:08
only need the pending here so I'm going to put that on my
23:10
to put that on my
23:10
to put that on my button and uh this has to be a client
23:13
button and uh this has to be a client
23:13
button and uh this has to be a client component because this is a
23:17
hook and you and it also needs some
23:20
hook and you and it also needs some
23:20
hook and you and it also needs some props which is going to be the
23:23
props which is going to be the
23:23
props which is going to be the children and if it's
23:26
children and if it's
23:26
children and if it's pending we can write render a nicely
23:29
pending we can write render a nicely
23:29
pending we can write render a nicely styled
23:31
styled
23:31
styled div with the a
23:35
spinner and the
23:39
spinner and the
23:39
spinner and the children and otherwise we will just
23:42
children and otherwise we will just
23:42
children and otherwise we will just render the
23:46
children um let's see if I can make this
23:50
children um let's see if I can make this
23:50
children um let's see if I can make this correct I think that's good there we
23:54
correct I think that's good there we
23:54
correct I think that's good there we go so let's try to import it and see if
23:57
go so let's try to import it and see if
23:57
go so let's try to import it and see if it works
23:59
it works
23:59
it works and I'm going to say hi and it's now
24:02
and I'm going to say hi and it's now
24:02
and I'm going to say hi and it's now using this submit button and it's
24:04
using this submit button and it's
24:04
using this submit button and it's handling everything for me the loading
24:06
handling everything for me the loading
24:06
handling everything for me the loading state is just there I'm just using a
24:07
state is just there I'm just using a
24:07
state is just there I'm just using a submit
24:08
submit
24:08
submit button and what's so great about this is
24:10
button and what's so great about this is
24:10
button and what's so great about this is I can throw this into any component like
24:12
I can throw this into any component like
24:12
I can throw this into any component like I can go to the message box and just
24:16
I can go to the message box and just
24:16
I can go to the message box and just toss it in there make it form with an
24:18
toss it in there make it form with an
24:18
toss it in there make it form with an action to reset my
24:23
messages
24:25
messages
24:25
messages um and I can just make an in line
24:28
um and I can just make an in line
24:28
um and I can just make an in line function
24:29
function
24:29
function here reset messages it's going to be a
24:32
here reset messages it's going to be a
24:32
here reset messages it's going to be a server action it's going to be
24:35
server action it's going to be
24:36
server action it's going to be slow it's going to delete messages from
24:39
slow it's going to delete messages from
24:39
slow it's going to delete messages from my database and it's going to revalidate
24:41
my database and it's going to revalidate
24:41
my database and it's going to revalidate the
24:46
path and if I now import all the things
24:48
path and if I now import all the things
24:48
path and if I now import all the things that I
24:50
that I
24:50
that I need and there we go we can see what
24:54
need and there we go we can see what
24:54
need and there we go we can see what happens so this is server component I
24:56
happens so this is server component I
24:56
happens so this is server component I don't have any use client here and still
24:59
don't have any use client here and still
24:59
don't have any use client here and still this submit button is handling the
25:00
this submit button is handling the
25:00
this submit button is handling the entire uh interactive feedback here for
25:04
entire uh interactive feedback here for
25:04
entire uh interactive feedback here for me and one more thing uh I want to show
25:08
me and one more thing uh I want to show
25:08
me and one more thing uh I want to show is the use
25:09
is the use
25:09
is the use optimistic so let's just get rid of all
25:12
optimistic so let's just get rid of all
25:12
optimistic so let's just get rid of all this code and uh jump over to an
25:14
this code and uh jump over to an
25:14
this code and uh jump over to an optimistic Branch really
25:17
optimistic Branch really
25:17
optimistic Branch really quick and in here I haven't done that
25:20
quick and in here I haven't done that
25:20
quick and in here I haven't done that much but I've made a messages component
25:23
much but I've made a messages component
25:23
much but I've made a messages component which is client component because it's
25:24
which is client component because it's
25:24
which is client component because it's using the use optimistic cook and what
25:27
using the use optimistic cook and what
25:27
using the use optimistic cook and what this does is take in a state to show
25:29
this does is take in a state to show
25:29
this does is take in a state to show when no action is pending which is going
25:31
when no action is pending which is going
25:31
when no action is pending which is going to be our truth from the server and an
25:34
to be our truth from the server and an
25:34
to be our truth from the server and an update function which says that an
25:35
update function which says that an
25:35
update function which says that an optimistic message will have an is
25:37
optimistic message will have an is
25:37
optimistic message will have an is sending
25:39
sending
25:39
sending true and then I'm going to pass the
25:41
true and then I'm going to pass the
25:41
true and then I'm going to pass the function to update uh to trigger the
25:43
function to update uh to trigger the
25:43
function to update uh to trigger the optimistic update uh to my message input
25:45
optimistic update uh to my message input
25:45
optimistic update uh to my message input and also use the optimistic messages for
25:47
and also use the optimistic messages for
25:47
and also use the optimistic messages for my
25:48
my
25:48
my display and in the message input I'm
25:51
display and in the message input I'm
25:51
display and in the message input I'm just doing the optimistic update in an
25:53
just doing the optimistic update in an
25:53
just doing the optimistic update in an unsubmit while leaving the uh action as
25:56
unsubmit while leaving the uh action as
25:56
unsubmit while leaving the uh action as a fallback
25:59
a fallback
25:59
a fallback so let's just see how that feels when I
26:01
so let's just see how that feels when I
26:01
so let's just see how that feels when I say hey I'm getting optimistic uh
26:05
say hey I'm getting optimistic uh
26:05
say hey I'm getting optimistic uh everything's happening right away and I
26:06
everything's happening right away and I
26:06
everything's happening right away and I get the sending here while the server is
26:09
get the sending here while the server is
26:09
get the sending here while the server is settling and replacing the client state
26:12
settling and replacing the client state
26:12
settling and replacing the client state with the message that does not have the
26:14
with the message that does not have the
26:14
with the message that does not have the ascending
26:15
ascending
26:15
ascending flag
26:17
flag
26:17
flag hi and as you can see we're having
26:19
hi and as you can see we're having
26:19
hi and as you can see we're having optimistic optimistic messages all
26:22
optimistic optimistic messages all
26:22
optimistic optimistic messages all resolving can send a couple more and
26:25
resolving can send a couple more and
26:25
resolving can send a couple more and when I hit my Max message count here
26:28
when I hit my Max message count here
26:28
when I hit my Max message count here the optimistic message will be roll back
26:32
the optimistic message will be roll back
26:32
the optimistic message will be roll back because it does not exist in the service
26:34
because it does not exist in the service
26:34
because it does not exist in the service state and this is all still Progressive
26:36
state and this is all still Progressive
26:36
state and this is all still Progressive enhanced by the
26:38
enhanced by the
26:38
enhanced by the way so uh of course depending on the app
26:40
way so uh of course depending on the app
26:40
way so uh of course depending on the app you don't have to make progressiv
26:42
you don't have to make progressiv
26:42
you don't have to make progressiv enhanced forms or anything like that but
26:44
enhanced forms or anything like that but
26:44
enhanced forms or anything like that but now by using these more primitive
26:46
now by using these more primitive
26:46
now by using these more primitive features of react 19 um with react react
26:49
features of react 19 um with react react
26:49
features of react 19 um with react react surf components we can make our forms
26:51
surf components we can make our forms
26:52
surf components we can make our forms very robust while maintaining a great
26:53
very robust while maintaining a great
26:53
very robust while maintaining a great user
26:54
user
26:55
user experience and these are probably going
26:56
experience and these are probably going
26:56
experience and these are probably going to be used as Primitives for other
26:58
to be used as Primitives for other
26:58
to be used as Primitives for other Library authors to U make for example
27:00
Library authors to U make for example
27:00
Library authors to U make for example form libraries that make it easier for
27:01
form libraries that make it easier for
27:01
form libraries that make it easier for us normal
27:03
us normal
27:03
us normal developers I'm almost done here I'm just
27:05
developers I'm almost done here I'm just
27:05
developers I'm almost done here I'm just going to quickly round it off um by
27:08
going to quickly round it off um by
27:08
going to quickly round it off um by saying that form actions exist in other
27:11
saying that form actions exist in other
27:12
saying that form actions exist in other Frameworks as well but now we have them
27:14
Frameworks as well but now we have them
27:14
Frameworks as well but now we have them in next and it's great we can make do a
27:17
in next and it's great we can make do a
27:17
in next and it's great we can make do a lot more than we could before with a lot
27:18
lot more than we could before with a lot
27:18
lot more than we could before with a lot more code a lot less code
27:22
more code a lot less code
27:22
more code a lot less code sorry and the repo for uh the demo is
27:25
sorry and the repo for uh the demo is
27:25
sorry and the repo for uh the demo is here on GitHub uh and then the optim
27:28
here on GitHub uh and then the optim
27:28
here on GitHub uh and then the optim update is in a branch if you want to
27:29
update is in a branch if you want to
27:29
update is in a branch if you want to check that
27:32
out and references uh most of what I've
27:35
out and references uh most of what I've
27:35
out and references uh most of what I've done is just from exam it can just be
27:37
done is just from exam it can just be
27:37
done is just from exam it can just be found in the docs and the react docs
27:40
found in the docs and the react docs
27:40
found in the docs and the react docs have more in-depth explanations and also
27:41
have more in-depth explanations and also
27:41
have more in-depth explanations and also considering the client side more than
27:43
considering the client side more than
27:43
considering the client side more than just the server that the xgf
27:46
just the server that the xgf
27:46
just the server that the xgf stocks uh yes I have a Twitter I post RC
27:49
stocks uh yes I have a Twitter I post RC
27:49
stocks uh yes I have a Twitter I post RC there excuse me RC stuff there and a
27:52
there excuse me RC stuff there and a
27:52
there excuse me RC stuff there and a Blog so if you're interested in learning
27:54
Blog so if you're interested in learning
27:54
Blog so if you're interested in learning more check that out thank you
28:02
[Music]


