
Join the Conversation!
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
Welcome to the evolution of form management in React. Learn how to build forms using the latest React hooks. Handle forms with server actions, use validation, form status, optimistic, and action state. In this course, we'll turn the basic form into three different forms, including a server form that works without client-side JavaScript. Use the useFormStatus hook to provide real-time feedback about form submission status. The useActionState hook helps manage the state of a server action in React server components. The useOptimistic hook enables the creation of optimistic UIs. The useTransition hook distinguishes between urgent and non-urgent state updates. The useDeferredValue hook defers updating a part of the UI to keep it responsive during expensive updates. Practice and experiment to learn these concepts.
"Please login to view comments"
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
How did you manage to remove the blur property and reach here?
Upgrading gives you access to quizzes so you can test your knowledge, track progress, and improve your skills.
By logging in, you'll unlock full access to this and other free tutorials on JSM Pro.
Why? Logging in lets us personalize your learning experience, track your progress, and keep you in the loop with new workshops, coding tips, and platform updates.
You'll also be the first to know about upcoming launches, events, and exclusive discounts.
No spam—just helpful content to level up your skills.
If that sounds fair, go ahead and log in to continue →
Enter your name and email to get instant access
##Looks like we found a thief monkey By the way, I liked the trick how you reached till here. You have a good sense of humor. You will improve a lot if you join our course with this passion.
var
(function-scoped, outdated)let
(block-scoped, modern and recommended)const
(block-scoped, cannot be reassigned)_
, or $
let let = 5;
is invalid)myVar
and myvar
are different)string
, number
, boolean
, null
, undefined
, bigint
, symbol
Objects
, Arrays
, Functions
Subscribing gives you access to a brief, insightful summary of each lecture to stay on track.
00:00:00 Hi there, and welcome to the evolution of form management in React.
00:00:05 Sounds a bit clickbaity, but yeah, it is not.
00:00:08 We'll dive into how React forms have evolved over time.
00:00:12 And I'll teach you how we can build forms using the latest React hooks.
00:00:18 A lot has changed in the React world with the introduction of new features which I'll cover today to help you ship faster.
00:00:25 So today, you'll learn how to handle forms with server actions, use new hooks like use transition, use form status, use optimistic,
00:00:38 and use action state to simplify state management.
00:00:41 And you'll also learn how to integrate validation and error handling into your apps.
00:00:46 But we won't just immediately dive into the new stuff.
00:00:50 I'll first take a traditional form that is handled using the useState and useEffectHooks, something we're already all used to,
00:01:00 and then step by step we'll upgrade it to modern React patterns.
00:01:05 You'll walk away from this workshop with the knowledge on how to handle forms in React along with practical knowledge on different hooks for robust air
00:01:17 handling and of course handling forms in the first place.
00:01:20 So without wasting any time on setup, I prepared a starter repo for you.
00:01:26 I believe it has been attached as one of the things to prepare for this workshop, but there's one thing I want to say.
00:01:33 We're going to go through some of the things fairly fast and although you will be able to ask questions, what I would advise personally is for you to give
00:01:43 this first workshop just a sit through, just watch it, see what I'm doing, how I'm traversing the code base.
00:01:50 And then later on, you can take that starter code base and turn it into the final code base by replicating what you learned in this workshop.
00:01:58 Okay.
00:01:59 So that's one thing that I would first of all recommend, even though if you want to, you can download the starter repo.
00:02:06 And I'm going to drop in a link as well.
00:02:10 Or do you guys already have it?
00:02:12 If not, I'll drop it right now in the chat.
00:02:14 Just so you have it for later for reference.
00:02:17 There we go.
00:02:18 There we go.
00:02:19 There it is.
00:02:19 Perfect.
00:02:20 That makes sense.
00:02:22 But as I said, first I would advise just going through it exactly what Android is going to do.
00:02:26 That's great.
00:02:26 And then later on, you can implement those things on your own.
00:02:31 Now, there's one thing I want to say.
00:02:33 Before getting started, it's important that we'll be using Next.js in this application.
00:02:40 Even though this is about React hooks, does anybody know a reason why we're going to use Next.js to show latest React 19 stuff?
00:02:50 Feel free to jump right in if you have any questions or if you have answers to that.
00:02:54 I can see that in the chat as well.
00:02:55 Yeah, Andre is basically right, because it doesn't work anywhere else yet, right?
00:03:00 Right now, it's very hard to replicate or put React 19 features to practice, as Nix.js is just the simplest way to spin up a new React 19 application,
00:03:11 okay?
00:03:12 So that way, you can very easily test out all the new features.
00:03:16 Even though it doesn't work anywhere else yet, it will start working very, very soon, and it's going to become basically globally accepted.
00:03:24 And even though it might not feel like it, most of the Nix.js features like React server components and more are basically the main features of React 19.
00:03:34 And now I thought long and hard how I'm going to approach this workshop.
00:03:39 One thing that I had in mind is just to go through this long demo with you and try to stumble as little times as possible.
00:03:49 And that was one valid approach.
00:03:50 But the second thought I had is, What if I do something that I do often on the internet?
00:03:58 If you don't know, I run a YouTube channel called JavaScript Mastery.
00:04:03 We just recently passed a million subscribers, so that was a big milestone.
00:04:07 But what we do on there is we record educational YouTube videos to teach people different concepts.
00:04:13 And I actually took some time out of my day today to prepare a quick video for you that's going to be short, sweet, and up to the point,
00:04:23 perfectly explaining those concepts.
00:04:25 So what do you say that I go ahead and play it for you?
00:04:28 It's going to be It's going to go through this demo, but I'm going to leave the best of the hooks that I want to explain for the end,
00:04:35 where I'll actually jump in once again, and then we can do it in a typical workshop style.
00:04:41 Of course, at every single point in time, you'll be able to make me stop, ask questions, and I'll be here to answer all those questions.
00:04:47 But I just thought it might be a bit better to do it in a more consistent video type style.
00:04:54 So with that in mind, I will switch my screen to this video right here, which you should be able to see, and I'm going to let it play.
00:05:03 And if you have any questions, always let me know.
00:05:05 I'll stop it and I'll answer any questions that you might have.
00:05:09 So with that in mind, first we'll dive into the explanation of the starter code, how it works, and then slowly I'll start converting that starter code
00:05:21 into using different types of forms that we can nowadays do in React 19 using different hooks, such as use optimistic, use action state,
00:05:30 use transition, and more.
00:05:31 One by one, we'll be improving our forms from the basic one to the end ones.
00:05:36 Of course, we'll do the last ones together live, but for now I wanted to prep something for you.
00:05:42 So I'll play it.
00:05:43 You can let me know by a thumbs up if you can hear the audio and I would advise just following along.
00:05:48 The app is called Code Confessions.
00:05:51 And it is a hangout space for developers to share their weirdest coding secrets and funniest debugging fails.
00:05:58 In other words, it is a simple CRUD application that allows developers to submit their confessions with a code name, weapon of choice,
00:06:07 which is their debugging weapon.
00:06:09 It's the coffee drip or rubber duck army or something else.
00:06:13 And finally, they can write their confession.
00:06:15 Once they submit it, we can simply review all of those confessions right here in a simple list.
00:06:20 The app is fairly simple and that is for a reason.
00:06:24 I wanted to specifically focus on the topic of this course.
00:06:28 So to test it out, let's go ahead and give it a shot.
00:06:32 We can enter our confession name.
00:06:34 That's going to be something like a coding ninja.
00:06:36 I know is a term used often.
00:06:38 We can use the weapon of choice.
00:06:40 It's definitely a control Z time machine.
00:06:43 And then I can enter my confession.
00:06:45 I'm going to say I use console logs for debugging.
00:06:50 Not the best way, but hey, works for me.
00:06:53 So let's go ahead and submit it.
00:06:56 And immediately, you can see it right here, I use Consolux for debugging.
00:07:00 So now you might be asking yourself, hey, Adrian, why are you giving me the finished code for this entire course?
00:07:06 What am I going to learn?
00:07:07 Well, here's the kicker.
00:07:09 This is just your standard, good old React code, using all the past practices, but none of the new React patterns that have been introduced.
00:07:19 So what we'll do in this course is we'll take the existing code and I'll teach you how to improve it.
00:07:24 So let me give you a quick overview of the current codebase.
00:07:28 Head over to app and then page.dsx.
00:07:31 Here, you'll notice that we're rendering a single basic form, which is rendered on the client side.
00:07:36 We'll turn this basic form into three different forms, each teaching you a new concept.
00:07:43 So if you check out components and then forms, you can see that we currently have a basic form, but you'll also learn how to implement a server form,
00:07:51 which is a form that works without client-side JavaScript, as well as a form that uses the use form status hook, and finally,
00:07:58 a form that uses the use action state hook.
00:08:02 We'll go over all of that today.
00:08:04 And within here, you'll learn how to implement the use optimistic hook and see how it improves the user experience.
00:08:10 There's also a search page where we'll implement the use transition as well as the use deferred value hooks for filtering.
00:08:19 And when it comes to where we're pulling the data from, it's going to be AppRite.
00:08:23 It's just a backend solution that I decided to use for this course.
00:08:26 Now, if you go to lib apprite.ts, you can see that I created some server actions like getConfessions, createConfessions,
00:08:33 search, and filter.
00:08:35 Basically what we're doing here is pretty simple.
00:08:37 We connect to our backend, we hook up to our database, and then we just try to fetch the documents in this case, and then return them.
00:08:46 I want to mention one thing, and that is that whatever you're learning in this course is fully adaptable to whatever other backend or database you're using.
00:08:54 So if you want to use MongoDB, you can.
00:08:56 If you want to use Postgres, that's totally okay as well.
00:08:59 The only thing you have to do is change the code within these server actions.
00:09:04 In the same way, we have a create confession where we take some parameters and then we create a new document to the database and then return its ID.
00:09:12 And in the same way, we search and we filter.
00:09:15 This doesn't matter too much for the purposes of this course.
00:09:18 What matters more is it's actually creating and fetching the data in an optimized way.
00:09:24 And finally, there is also a confessions component right here, which is responsible for displaying all of these confessions after they get fetched.
00:09:33 We'll reuse it a lot through our application to display this data.
00:09:36 So now that you know a bit about this code base, what do you say that we actually get started modifying the code?
00:09:42 As you know, we currently have a basic form.
00:09:46 and it's just your good old regular React form.
00:09:49 We have different use states for managing different fields, as well as a use state for loading, and we have a function that handles the submit.
00:09:56 We clear the form, and then we actually pass the submit handler to the form, and then we submit it by pressing a button.
00:10:04 Pretty straightforward, right?
00:10:06 And one thing that you can see is that right here in the handle submit, we're actually calling the create confession server action to create our confession.
00:10:15 And I already showed you how it worked at the start when we saw the demo.
00:10:19 We have added one new confession.
00:10:21 But now, if you go back to the browser, if you inspect element, and if you disable JavaScript by pressing Ctrl or Command-Shift-B and then run Disable JavaScript,
00:10:33 if you reload and try to submit the form, let's give it a shot.
00:10:37 I'll enter some random values right here.
00:10:40 you'll see that you won't even be able to select your weapon of choice because it's a drop-down and you cannot click a submit button.
00:10:46 So it doesn't work.
00:10:47 But even if we didn't have this weapon of choice, you would not be able to submit it because it is a client-side form.
00:10:53 Not ideal.
00:10:55 So let me show you how we can develop a form that works without client-side JavaScript.
00:11:00 We can do that by using the built-in browser form that is supported in newer React version, which behaves like a standard HTML form.
00:11:09 So head over to Components and open up Forms, serverform.tsx.
00:11:15 This form right now is exactly the same as the basic form.
00:11:19 I just copy and pasted it and changed the file name.
00:11:22 But now, let's actually make it into a server form.
00:11:25 I'll do that by first removing the useClient, because it'll no longer be rendered on the client side.
00:11:31 And this is something that might look very weird, because the forms typically have some buttons, and buttons have onClicks,
00:11:37 and onClicks are client side.
00:11:39 But bear with me, it'll all work on the server side.
00:11:42 We can also remove all of the states from here, because no longer we will be using any hooks.
00:11:48 Next, we'll remove all the functions like this handleSubmit right here, as well as the handleClear.
00:11:55 We'll replace the onSubmit on the form into a prop called action, and we'll make it call the form action.
00:12:04 We'll also remove the value and onChange from all of the inputs.
00:12:09 That's going to be the first input.
00:12:11 The select as well.
00:12:15 And finally, the text area.
00:12:17 Let's also remove the on click from these buttons, as well as the disabled state.
00:12:24 And unfortunately, we won't be able to show the loading because we don't have any state anymore.
00:12:30 We can also change the type of the clear button to be a type reset, which will make it automatically reset the form.
00:12:39 And we can head back over to our inputs.
00:12:41 Let's start with the first one.
00:12:44 And give it a name attribute.
00:12:46 So the name in this case will be name.
00:12:48 We can do the same thing for select.
00:12:51 So select will have its own name equal to weapon.
00:12:56 And finally, the text area will also have its name.
00:13:00 It will allow us to extract the values from the form.
00:13:04 And finally, we are ready to implement the form action server function.
00:13:10 So let's create a new asynchronous function.
00:13:14 called form action that accepts the form data of a type form data.
00:13:21 And at the top of it, we can add one directive, a directive called use server, which means that this asynchronous function will be called only on the server side,
00:13:33 making it a server function.
00:13:36 Now within here, we can get the data from the form data by saying const name is equal to form data dot get name as string.
00:13:45 We can also get the weapon as string.
00:13:47 And finally, we can get the confession as string as well.
00:13:53 Once we have that, we can open up a new try and catch block.
00:13:57 For the error, we can simply try to console log this error.
00:14:03 And for the try, let's try to get the result of a successful submission by saying await, create confession, and pass in the name,
00:14:12 weapon, and the confession itself.
00:14:14 And if the result is not there, that must mean that something went wrong.
00:14:19 So we can throw a new error saying failed to create confession.
00:14:25 Okay.
00:14:25 So you can think of this to be very similar to a form submit, but it is actually a server action that submits the form.
00:14:34 I will remove all the unused imports, as well as the use state, and fix all the typos.
00:14:42 And since we no longer have client-side JavaScript, we won't be able to click on here and select one of the options.
00:14:49 For that reason, for the time being, I'm just going to simply make this static.
00:14:53 And I'll say that my weapon of choice is coffee.
00:14:57 A lot of coffee.
00:15:00 And we also have to head down and remove the required property from the select.
00:15:05 Or if we didn't have select at all, like just some simple inputs, then this would have totally worked.
00:15:10 But since we're using a Schatzian UI select component, it is a client component with plenty of JavaScript baked into it.
00:15:17 So that's why we cannot use it on the server side.
00:15:20 And you may think, okay, we removed a couple of things like the toast indicator and loading states, and hey, even the select element.
00:15:29 But for what?
00:15:30 Well, to see whether this works without client-side JavaScript.
00:15:34 So let's actually test it out.
00:15:37 I'll head to my browser and I'll open up Developer Tools by right-clicking and clicking Inspect.
00:15:44 Then I'll press Cmd or Ctrl Shift B and I'll run Disable JavaScript.
00:15:50 Press Enter.
00:15:51 And to make sure whether it worked, try to press Cmd or Ctrl Shift B again and search for Enable JavaScript.
00:15:58 If it's there, it means it has been properly disabled.
00:16:01 And for it to remain disabled, you must not close Developer Tools right here, because then it'll start working again.
00:16:08 Another way to test it is if you click here, you'll see that it won't actually open.
00:16:13 So let's go ahead and give it a shot.
00:16:15 I'll copy some of the previous coding confessions, like this binary ninja as the name, as well as its confession saying something like,
00:16:25 I once spent three hours debugging only to realize my computer wasn't even plugged in.
00:16:31 This makes me think they're being paid by the hour.
00:16:33 So let's go ahead and click submit.
00:16:36 And it doesn't want to do it.
00:16:37 I think I know why that is.
00:16:41 I think I know why that is.
00:16:42 Coffee, a lot of coffee is not actually a valid weapon.
00:16:46 In AppRide, we specify the weapon field as an enum.
00:16:49 So if you head over to utils, you'll see some of the possible options for that enum.
00:16:54 So it looks like I'll have to choose a different weapon.
00:16:57 Let's go with other mystical artifact.
00:17:01 So if I fix this over here, go back and reload, make sure that my JavaScript is disabled by not being able to open the select.
00:17:11 I'll once again type in my code name, as well as my confession.
00:17:17 And I'll click submit.
00:17:20 And now it worked.
00:17:21 And if you head over here, you can see that Binary Ninja successfully submitted their newest confession completely on the server side with JavaScript being
00:17:31 completely disabled.
00:17:32 Isn't that amazing?
00:17:33 This entire form works completely on the server side.
00:17:37 due to the action prop which is tied to the form server action.
00:17:42 This works because React's action prop is actually being infused to the built-in browser form, and we don't need any JavaScript to submit it.
00:17:51 And I actually want to dive into this in a bit more detail.
00:17:55 See, under React documentation here, you can see that an action is a URL or a function.
00:18:01 And when a URL is passed to the action, the form will behave like the HTML form component.
00:18:06 When a function is passed to action, the function will handle the form submission.
00:18:11 And that's it.
00:18:11 You can submit it on the client.
00:18:13 and you can also submit it on the server using the way that I just explained.
00:18:17 But you may say, hey, this is super cool, but what is it good for if I can't even show if the submission progress is loading or show a success or false
00:18:28 message once it is submitted?
00:18:30 How can I do that?
00:18:31 UX matters.
00:18:33 Look, you can't do everything on the server side, and you shouldn't either.
00:18:39 You would never want to have hundreds or thousands of dollars in server costs.
00:18:43 Instead, you should learn how to balance your application and your requirements to implement the features you want.
00:18:49 To achieve the desired features, we'll use the Use Form Status Hook, paired with this form we created.
00:18:57 So what is the use form status?
00:18:59 Well, it is a hook that provides information about the status of the nearest form element.
00:19:05 It's used to give real-time feedback about form submission status.
00:19:10 And we use it when you want to show loading indicators or disable buttons while a form is submitting.
00:19:16 Exactly what we want it to do.
00:19:18 Here is how its syntax looks like.
00:19:21 You call it, just as you would any other hook, and from it, you destructure different properties, like pending, data, method,
00:19:28 and action.
00:19:29 The pending boolean indicates if the form is currently being submitted.
00:19:34 allowing you to show loading states or disable submit buttons.
00:19:38 And the data, method, and action properties give you access to the form's current data, HTTP method, and the action URL.
00:19:46 So going back to the code, let's go to forms, use form status, index.tsx.
00:19:52 This file contains the same exact code from our server form.
00:19:56 And implementing this useForm status hook will require the whole component to be client-side.
00:20:02 Instead of doing that and making this whole component client, let's create a new file right inside of this folder.
00:20:09 I'll call it submit.tsx.
00:20:12 And within here, we can run RAFCE to quickly spin up a new submit component.
00:20:18 We'll give it a useClient directive to render it on the client.
00:20:22 And let's quickly form the UI of this component by giving it a class name, equal to flex, justify-end, and space-x-4 to position it nicely on the screen.
00:20:35 Let's render a button within this div coming from Components' UIButton, that is from ChatCN, with a type of reset.
00:20:44 Let's also give it a variant of Outline, as well as a class name of PaddingX of 8, to give it some space to breathe.
00:20:53 The button itself will simply say Clear.
00:20:55 Right below it, we can create a different button.
00:20:59 This button will be of a type Submit, and it'll have a class name equal to bgBlack.
00:21:07 On hover, bgGray800.
00:21:12 Text dash white and padding X of eight.
00:21:17 And it's simply going to say submit.
00:21:19 Now let me show you how we can get access to the pending status of the nearby form and attach it to the submit button.
00:21:27 The only thing you have to do is say const destructure the pending status.
00:21:33 by calling the useFormStatus hook coming from React DOM.
00:21:39 And you can use it in whichever way you want.
00:21:41 For example, while the form submission is pending, we can make this button disabled by saying disabled.
00:21:49 is equal to the pending status.
00:21:52 And in the same way, we can show a loading indicator by saying if pending is true.
00:21:57 Then we can render a refresh CCV, which is just an icon coming from Lucid React icons.
00:22:05 to which we can pass a class name of marginRightOf4 of marginRightOf1 to divide it a bit from the submit text, h4 and w4 to give it some height and width,
00:22:19 and animate-spin which will spin it around.
00:22:22 And now we can go back to the index.tsx of the useForm status component, and we can replace the button code with this new submit component.
00:22:33 So let's delete it, including the div, and simply render the self-closing submit component coming from .slash submit.
00:22:40 It looks like it's complaining a bit here because it didn't properly wrap the return.
00:22:46 So let's wrap it right here to actually know what it's returning.
00:22:50 There we go.
00:22:51 And we can invent it properly.
00:22:53 Now, the only remaining warning right here is the fact that we're no longer using this client-side rendered button.
00:22:59 We have our own client-side render component within this server-side form.
00:23:03 But hopefully, now our server-side rendered form will get just a bit smarter.
00:23:08 So, let's go back to the page.tsx.
00:23:12 That's the home page.
00:23:14 And instead of using the regular server form, now let's use the use form status form.
00:23:23 And as a matter of fact, I want to keep all the forms here, like the basic form, but I'll just comment it out.
00:23:31 And then we had the server form as well.
00:23:34 Just to know how we slowly progressed from the basic ones to a bit more advanced forms.
00:23:39 Back in the browser, let's try to submit another form.
00:23:42 I'll copy some other thing from Syntax Samurai, and let's see what it says.
00:23:49 I accidentally pushed my cat's keyboard walks to production.
00:23:53 Okay, that makes sense.
00:23:54 And in this case, we can select our debugging weapon.
00:23:57 It's gonna be some mystical artifact, in this case, the cat.
00:24:01 So let's go ahead and submit it.
00:24:04 And check it out.
00:24:04 It's actually showing you the submitting status.
00:24:08 And you weren't able to click anything or touch it while it was submitting.
00:24:13 So this means that now we have a server rendered form.
00:24:16 We still need client-side JavaScript though, for this little thing to work.
00:24:19 But if we didn't have that, you could technically have a completely server rendered form.
00:24:24 But now, using the use form status, you can get the pending state of the form to be able to show some kind of loadings or disable additional clicks.
00:24:32 And of course, you can take it further from here.
00:24:35 You can get a response back from the server, whether it's successful or not.
00:24:39 As you know, the use form status returns a couple of things.
00:24:43 pending, data, method, and action.
00:24:47 So you can...
00:24:48 So you can totally know whether it succeeded or not, and then display some kind of a message to the user.
00:24:54 But for that, there's a hook that does it...
00:24:56 But for that, there's a hook that does it a bit...
00:24:58 But this one doesn't really tell you whether it's successful or not.
00:25:01 You can just see whether some data was returned and whether it's pending or not.
00:25:05 This feels like some kind of an experiment hook from React team.
00:25:08 So we're going to use a different one to improve this form even further.
00:25:12 So let's do it using the useActionState hook.
00:25:16 It allows you to manage the state of a server action and React server components.
00:25:21 It provides a way to handle the lifecycle of server actions and update the client-side UI based on...
00:25:27 So what is it?
00:25:29 Well, it's a hook that manages the state of an action like a form submission in React server components.
00:25:36 It's used to handle the lifecycle of server actions and provide client-side updates.
00:25:42 And we use it when working with server actions in Next.js specifically for form submissions that need to update the UI based on the server response.
00:25:52 Of course, what we care about is the syntax.
00:25:55 It works very similarly to any other React hook.
00:25:58 The state that you get back is the current state of the action.
00:26:02 The action is the function that you can call to trigger the server action.
00:26:05 And then isPending indicates whether the action is currently in progress or not.
00:26:11 Basically, it's an all-rounder hook that is doing everything for you so you can focus on the business logic.
00:26:16 To implement it, let's head over to components.
00:26:21 forms useAction.
00:26:25 Once again, we're starting with a regular server rendered component, but this time we'll turn it into a useClient component to be able to use this grade
00:26:34 function hook.
00:26:35 So let's do it right here at the top.
00:26:37 By saying const, we can destructure the state, the form action, and the isPending state by calling this hook useActionState coming from React.
00:26:53 And to it, first things first, you need to pass the action you want to call.
00:26:57 In our case, what we want to do is submit a confession.
00:27:02 So that's going to look something like this.
00:27:05 And this submit confession is basically a callback to the server action.
00:27:09 So we can modify the submit form action here and turn it into something that is not rendered in the server because now we're in the client side.
00:27:16 We want to utilize all the benefits that rendering forms in the client side gives us.
00:27:21 So let's call this submit confession.
00:27:25 And let's make it render on the client like this.
00:27:29 We can extract all of the properties.
00:27:31 We can open up a try and catch block and try to submit the confession.
00:27:36 We can also now use toasts coming from adhooks forward slash use toast.
00:27:42 Why?
00:27:43 Because we're on the client side.
00:27:44 So let's render a title of confession submitted and a description of your confession has been submitted successfully.
00:27:51 And finally, we can return success of true.
00:27:59 Same thing if something goes wrong, right here under the error, we can actually render a toast saying something like, something went wrong.
00:28:10 And for the description, we can just render the error message by saying error?
00:28:16 message.
00:28:18 And we can also render a variant equal to destructive.
00:28:26 If we want to make TypeScript happy with this property message, we need to do some TypeScript error handling by saying const errorMessage is equal to if
00:28:36 error is an instance of error, then we return the error.message because it exists on it.
00:28:43 But if the error is not an instance of error, then we can say something went wrong.
00:28:48 And then we can just use the errorMessage as a string.
00:28:52 As you can see, it gives us more possibilities to display something to the user when we're not working on the server side.
00:28:59 But still, we can leverage all of the great things that the use action state gives us.
00:29:04 Now, I just noticed that here I passed success to true, whereas it should have been false if something goes wrong, and we can also pass the error equal
00:29:12 to error message.
00:29:14 Another thing you can notice is that this use action state is actually complaining that it wants to get two to three arguments,
00:29:20 but it got one.
00:29:21 The second argument is actually the initial state, which we can pass as undefined for now.
00:29:28 After we fix that, it's complaining about the structure of the submit confession.
00:29:32 And if you go into it, we will have to slightly modify the parameters that this function accepts, because the first parameter is the prev state.
00:29:42 which is going to be of a type any, and then only after that do we get access to the form data.
00:29:48 For now, my TypeScript is complaining a bit, so I can just disable TypeScript for the next line saying no explicit any.
00:29:56 We're not using this pref state anyway in this application.
00:30:00 So with that, we get access to a couple of different properties, state, form action, and isPending.
00:30:06 Now the submit confession is no longer a server action.
00:30:10 It is just a normal function, which will then call our server action create confession to create it.
00:30:17 Finally, we can now use this isPending state.
00:30:20 So let's hop down to our buttons.
00:30:23 And just above the submit, let's say isPending.
00:30:27 And if it is, we'll just say something like submitting, or you can use that refresh CCV that we saw, which is a spinning icon,
00:30:36 to which we can give a class name of MR1, H4, W4, and animate-spin.
00:30:47 We can also make it disabled if it is pending.
00:30:50 So we're basically doing the same thing that we did last time, but this time with the use action state hook.
00:30:56 Let's see if we have some more warnings.
00:30:58 Oh, we just have one that we're not using this state.
00:31:01 That's totally okay.
00:31:02 For the time being, we can just disable the no unused variables for the next line.
00:31:08 So now let's head back to our homepage and let's render this fourth form, which is going to be the use action state form.
00:31:16 And let's go back to the browser and test it.
00:31:19 I'll go with the third one now, which is going to be the bug whisperer.
00:31:23 And let's see, what did they say?
00:31:25 And it says, I dream in code and wake up with solutions and syntax errors.
00:31:30 So let's go ahead and submit it.
00:31:32 You can see the submit and now you can also see this toast because we're on the client side, right?
00:31:37 So now you have toasts, you have pending states and everything.
00:31:40 You have the same experience that you had with the first, the basic form, but now with less code, considering that we're using the use action state hook.
00:31:48 So it feels almost like we have done a full circle just to be able to use this hook.
00:31:54 But while doing that full circle, I hope you learned a thing or two about how form submissions work, both in the server side,
00:32:00 what are some of the drawbacks of server side forms, and how we can do new client side forms using the use action state hook in React.
00:32:08 Now, before we go ahead and check out the next hooks, I want to talk about server actions that we're using in this application.
00:32:15 If you head over to lib, appri.ts.
00:32:20 You can see all of these server actions we had.
00:32:22 They're completely normal functions, but they're rendered on the server side.
00:32:26 And the way it works is you can also call them via the client side or within components as well.
00:32:31 Next.js behind the scenes simply converts them into post requests.
00:32:36 Of course, you may not want to switch over to server actions completely.
00:32:40 That approach has its own pros and cons.
00:32:43 And actually, that's something that I talk in depth about within my Next.js course.
00:32:47 There's a whole dedicated module just on that topic.
00:32:50 So if you want to learn a bit more about Next.js alongside learning the latest of what React Hooks offer, you might want to check out the course on jsmastery.pro.
00:33:00 And server actions are cool and all, but you have to take precautions when using them.
00:33:04 Since this is supposed to be a simple demo website, I did not take those precautions.
00:33:09 But I want to show you how a code base including them would look like.
00:33:12 The code base for the ultimate Next.js course I created is completely free and open source.
00:33:17 Feel free to check it out, even if you don't buy the course.
00:33:20 But I want to take a look at it for a second to teach you some advanced server action best practices, such as how you can validate the data coming into
00:33:28 the form by creating an abstraction that you can call before you actually call any of the server actions you've created.
00:33:34 This generic function also includes some security checks and it always returns the data in a validated format.
00:33:42 So whenever you call it, you pass into it the params you want it to have and the schema it can validate.
00:33:48 That way you can focus on the business logic of your application and not making sure that you're error handling every single server action.
00:33:55 If you follow these best practices, you're good.
00:33:58 And once again, the source code is completely open source, so feel free to check it out and implement it on your apps.
00:34:04 Or if you want me to go over it with you in detail, feel free to get the course.
00:34:09 But now server actions aside, going back to our code, you'll notice that in the create confession, there is something known as a revalidate path.
00:34:19 This allows us to receive fresh dynamic data whenever you submit the form.
00:34:24 Without it, you would have to refresh your browser to see the latest submitted confession or whatever the data is.
00:34:30 I just wanted to point your attention to that as server actions, as well as this revalidated path in Next.js are something that is quite new.
00:34:37 And I wanted to make sure that you have full understanding of how it works.
00:34:41 Now let's improve our UX even further by using the use optimistic hook.
00:34:47 This hook allows you to create optimistic UIs where you show an immediate update to the user before the actual operation completes.
00:34:57 And here we are.
00:34:59 I'm back right here and I want to actually go over the use optimistic hook with you.
00:35:05 So right now we have just finished this part and we have used many different hooks, but the best ones are just coming.
00:35:12 So here we can focus on the use optimistic hook as well as the famous react use hook.
00:35:20 How did you find everything so far?
00:35:21 Was it a bit too fast maybe?
00:35:25 Especially if you're trying to code along, definitely too fast.
00:35:28 But if you're trying to just watch, was it okay?
00:35:31 Were you able to get access to kind of understanding of some of the hooks in React?
00:35:37 You can let me know in the chat if you like, or if you need me to clarify anything that was covered in the video.
00:35:42 While I'm waiting for that, I'll actually open up the code and the rest of the presentation.
00:35:46 There we go.
00:35:47 Yeah, Andrew say not coding along.
00:35:49 Yeah, that's great.
00:35:50 But we can basically, you can try to revisit some later on.
00:35:55 Now I'll re-go through the presentation that you had in the recording just to explain and reiterate some of the stuff that I explained there.
00:36:01 So the first thing that we noticed is that if you put everything on the server, first of all, not everything will work as people are expecting it to work.
00:36:10 You won't get the loading handlers, you won't get the toast, you won't get any kind of client-side functionality.
00:36:18 But another thing is that your server costs will go through the roof, right?
00:36:22 So you have to be very cautious and very thoughtful on what you're going to put on the server and what you're going to put on the client side.
00:36:32 You want to balance.
00:36:33 It's a balancing act basically between the two.
00:36:35 So let's see.
00:36:37 First, we explored the use form status, which allowed us to get access to the pending state of the form.
00:36:43 whether it's real-time feedback, mostly used for loading indicators and just disabling buttons.
00:36:52 Not super advanced.
00:36:54 You simply get the pending and the data and the method and the action from the use form status hook.
00:37:00 If the form is currently being submitted, then you get access to that data.
00:37:05 You also get the form's current data, the HTTP method being used, and the action URL.
00:37:10 But now the other hooks is the use action state, which lets you know exactly that.
00:37:16 What is the state of the action that you're trying to perform?
00:37:20 It gives you the full updates on the life cycle of that server action, as well as providing you client-side updates.
00:37:26 And you use it when you want to figure out whether you need to update the UI based on the server's response.
00:37:33 It looks something like this, where you get the state.
00:37:36 the action and the isPendingState to figure out whether you want to do the update.
00:37:40 And we also learned a bit more about server actions, about all the best practices and how we're using them within our code base.
00:37:47 And now we're diving into the useOptimisticHook.
00:37:50 So let me keep going by explaining how the useOptimisticHook works.
00:37:55 It's a hook that allows you to show an immediate optimistic UI update.
00:38:02 before an action completes.
00:38:05 What does this mean?
00:38:06 Well, we're all aware of optimistic updates, right?
00:38:09 Whenever you have something that could take a long time to do, but you actually want to show some information to the user immediately,
00:38:17 you want to do something called an optimistic update.
00:38:20 Give me a thumbs up in the chat of how many of you are actually aware of what optimistic updates are.
00:38:25 And maybe you have even used them before in your code bases.
00:38:28 Yeah, I cannot see any thumbs up.
00:38:30 That's interesting.
00:38:32 But I can see Edvin said in React queries or mutations.
00:38:35 Yeah, definitely.
00:38:36 That's one way to use them.
00:38:39 And React is not doing anything new here.
00:38:41 We are all aware of the concept of optimistic updates, but what you get with the useOptimisticHook is it makes it a bit simpler to perform that.
00:38:50 So you would use it whenever you want to update the UI instantly, while the actual operation is still in progress.
00:38:57 It looks something like this.
00:38:59 You call the use optimistic and to it, you pass the current state and an update function.
00:39:06 Then you get back a optimistic state, which reflects what the state would be after the optimistic update, as well as the add optimistic,
00:39:16 which is a function that you can call to apply the optimistic update.
00:39:20 And finally, I want to pair this hook with another hook because they work well together.
00:39:24 And that hook is the use hook.
00:39:28 Use simply with the simplest name possible is a powerful tool for reading the value of a resource.
00:39:36 The resource being either a promise, context, or something else.
00:39:42 It is particularly useful in concurrent environments where you want to unwrap their promises directly in your components or in their face.
00:39:51 So let me simplify it.
00:39:53 Use is a hook that lets you read the value of a resource, like a promise or context.
00:40:00 It is used to simplify working with asynchronous data or context in components, and you use it when you need to read a promise or context value within
00:40:10 your component, especially in concurrent mode.
00:40:13 The syntax is the simplest possible, like this.
00:40:18 First, you call it and you pass in the resource, and if that resource is a promise that hasn't yet been resolved, React will suspend the component and
00:40:27 show the nearest suspense fallback.
00:40:29 Before we dive into the use transition hook, and another one which I want to show you, I actually want to go back to the code and I want to explore the
00:40:37 use optimistic hook as well as the use hook.
00:40:40 So let's do some live coding now.
00:40:43 This is the same starter code base that you've seen in the recording, but now we're going to go into a different file.
00:40:49 Instead of working within the homepage, we'll work within the discover to discover some of the new hooks that we have.
00:40:56 First things first, here you want to get access to all of the confessions from AppRight.
00:41:02 So we can do something like const allConfessions is equal to getConfessions, which is coming from libAppRight.
00:41:13 And here I'm calling the useOptimisticForm, which is right now just the basic form you've seen already, but we're going to turn it into the optimistic
00:41:21 form with the addition of those two new hooks that we learned about.
00:41:26 Great.
00:41:28 So we want to pass all of these confessions, if I can spell them correctly.
00:41:36 There we go.
00:41:38 Into the use of the mystic form by saying something like confession promise is equal to all confessions.
00:41:50 Now, does anybody know why I didn't add the await right here?
00:41:56 It's because I want to pass the raw promise directly to the use optimistic form and not pass the already finished value,
00:42:05 okay?
00:42:06 So I'm simply passing the promise, get confusion, get non-add confusions, get confessions returns a promise.
00:42:14 So that's the promise that we're passing.
00:42:16 And we're doing that for a reason.
00:42:19 a photo right out of the documentation.
00:42:23 Let me just share it right here on your screen so you can see it.
00:42:27 It looks something like this.
00:42:30 There we go.
00:42:32 There we go.
00:42:33 So here in the documentation, it explains, should I resolve a promise in a server or a client component?
00:42:41 And it says that a promise can be passed from a server component to a client component and be resolved in the client component with a use API.
00:42:50 You can also resolve the promise directly in a server component with a wait and pass the required data to the client component as a prop.
00:42:59 We know that, right?
00:43:00 There's two different possibilities that you can do.
00:43:03 You can either await it here and pass the finished piece of data, or you can await it there once you actually get into the form.
00:43:11 But why would one way be preferable to the other?
00:43:17 Well, using await in a server component, which is the primary page we're on right now, will block its rendering until the await statement is finished.
00:43:27 But passing a promise from a server component to a client component prevents the promise from blocking the rendering of the server component,
00:43:36 making it that much more efficient.
00:43:39 So now let's head back to our code and go into the optimistic form where we'll actually accept this prop right here at the top by saying confession,
00:43:53 promise.
00:43:54 It's going to be of a type.
00:43:56 Confession promise is a promise that returns an array of confessions.
00:44:04 That's going to look something like this.
00:44:08 Next, we can implement the use optimistic hook.
00:44:11 So right here, I can say something like const confessions is equal to use confession promise, which you pass into it.
00:44:25 And this is how, when you import use from React, you can actually now resolve a promise in a client component.
00:44:35 Keep in mind, this is a client component.
00:44:38 But if you pass the entire value, you would not be able to just await it.
00:44:44 So if you were instead calling the getConfessions here and trying to skip this step, you would then have to do a wait, but you cannot make client components asynchronous.
00:44:54 So this would not be a viable option.
00:44:57 Instead, you have to do exactly what we have done right here.
00:45:01 First, get access to some kind of a promise, which promises that it's going to bring you back the data, pass it as a prop,
00:45:09 and then here, use the use function or the use hook to actually resolve that promise, which will turn into the confessions.
00:45:17 And now that we have the confessions, I want to immediately merge it with the use optimistic hook.
00:45:23 That's going to look something like this.
00:45:25 Const.
00:45:26 We can get something out of the use optimistic call, which is going to look like this.
00:45:33 And to it, we pass confessions as the first parameter.
00:45:37 So what we want to be optimistic for.
00:45:42 And then you pass a callback function, which is going to tell your React code how those confessions will look like after they actually get updated.
00:45:53 As the first parameter to this function, you're going to get the current state so you know what you can update.
00:45:59 After that, you're going to get the optimistic value.
00:46:04 Okay.
00:46:04 So you can update the current state with the value, which is going to be of a type optimistic confession.
00:46:11 And this is just a type which we have to define at the top.
00:46:14 And I purposely wanted to teach you how we can define it.
00:46:17 So you can understand the differences between an optimistic confession and the regular confession.
00:46:23 An optimistic confession is a type optimistic confession, which starts with the regular type of confession.
00:46:33 And then we can, it also has a property of sending.
00:46:38 So are we currently sending that thing to the server, which is of a type boolean.
00:46:44 If we're no longer sending it, if it's done, it's going to be false.
00:46:47 Else it'll be true.
00:46:49 And now we can just return a modified array.
00:46:54 where we have the optimistic value and where we spread the current state, meaning it'll contain all of the confessions, or in this case,
00:47:03 all of them that were there before, and the one that we after once we add that optimistic update, the one that we submit.
00:47:09 So with that in mind, we get something back out of this hook.
00:47:14 We get back the updated optimistic confessions, And that's going to be lowercase letter.
00:47:23 And we also get the actual function that allows us to optimistically add a confession by saying add optimistic confession.
00:47:34 That's going to look something like this.
00:47:38 Now we can add it directly to the form action.
00:47:44 By first saying const new confession.
00:47:49 is equal to, and it's going to have all of the other properties like the regular confession does, like the name, weapon,
00:47:57 confession, and it's going to have a sending to true because it's still not yet added to the server side.
00:48:03 And then we want to have the dollar sign ID property, because whenever you save something into the database, at least it will have the ID once it's saved,
00:48:13 but we have to replicate that here.
00:48:15 So we can say that ID is equal to date.now, and then we can string it by it.
00:48:21 So now this has everything that a real confession in the database will have.
00:48:26 And now we can add it optimistically by saying add optimistic confession.
00:48:31 And to it, we can pass the new confession.
00:48:34 Everything else remains exactly the same.
00:48:37 We're still creating a new confession in the database right here, but we're also doing so optimistically so we can automatically show the update.
00:48:46 And finally, we want to render all the confessions.
00:48:49 from optimistic confessions.
00:48:51 So if I go right here below, we can do something simple like optimistic confessions.map where we get each individual confession of a type,
00:49:05 optimistic confession.
00:49:06 And for each one, we simply return a div and that div will have a key equal to confession.$id since we're mapping over it.
00:49:17 And let's give it a class name equal to We'll use the CN property, class names from ShadCN that allows us to dynamically render different class names depending
00:49:29 on different criteria.
00:49:31 Every single div will have a transition dash opacity and a duration of 300. But only if confession.sending is true.
00:49:46 Then it'll also have the opacity of 50 and animate-false.
00:49:53 Set the true as well.
00:49:54 Else it'll have an opacity of 100. And within it, we want to render the confession item component.
00:50:03 which is going to look something like this.
00:50:05 It'll have a name equal to confession.name.
00:50:08 It'll have a weapon equal to confession.weapon and a confession equal to confession.confession.
00:50:16 Now, let me explain what's happening here.
00:50:18 We're mapping over all the confessions, including one which will be optimistic, the one that hasn't yet been added to the server or to the database.
00:50:26 And this check right here, whether sending is true or not, is displaying the card in some kind of a faded effect with only opacity 50, and it'll also be pulsating,
00:50:37 meaning that it's actually being added to the database.
00:50:41 And then once it actually completes getting added to the database, it'll change to opacity 100 to make it appear like just a regular card.
00:50:49 And now to see this optimistic event in action properly, let's head over to Apprite.
00:50:56 So that's going to be Apprite lib.
00:50:59 And right here, where we have create, I want to turn on a 10 second delay, just so we can kind of have more time to check how it's actually being optimistically added.
00:51:12 If we didn't have it, it would just happen immediately, especially if you have a fast connection, but now we're purposefully delaying the action so we
00:51:19 can see the optimistic updates more closely.
00:51:22 Now let's head back over to the website.
00:51:25 Let me open it up right here.
00:51:28 And I'll head over to the forward slash discover page, which uses the use optimistic hook form.
00:51:33 We have all the connections here or confessions.
00:51:36 And now I can create a new one.
00:51:38 Let's say something like testing.
00:51:42 Let's do optimistic updates.
00:51:46 Select my debugging weapon and we can add my confession.
00:51:50 That's going to be something like testing things live in a workshop and I'll click submit.
00:51:58 Check this out.
00:51:58 You see this opacity 50 pulsating card effect.
00:52:03 which immediately it showed.
00:52:06 And you could also add something like getting added to the database, like a text here.
00:52:10 And then after 10 seconds, it automatically got added.
00:52:13 And now we can see that it actually belongs where it should be.
00:52:17 This is pretty cool.
00:52:19 because you can optimistically, in a very simple way, natively within React, add UI changes depending on no matter whether the connection is fast or slow.
00:52:32 If it's fast, you might not even see it.
00:52:34 That's okay.
00:52:35 But on slower connections, this will be a big difference, trust me.
00:52:41 It's easy to show a loading, but if you have large pieces of data, it's much better to show an optimistic update rather than a loading,
00:52:49 especially if you're almost sure that it'll actually be properly executed on the server, which most create actions will anyway.
00:53:00 Pretty cool, right?
00:53:02 So we have kind of gone from very simple basic forms to now having optimistic updates natively using some React hooks that are built into it.
00:53:13 And we can see that in the Discover page right here, where we have both the use hook as well as the use optimistic hook.
00:53:23 Now, right here, we have Two more hooks I actually want to go over.
00:53:30 Those hooks are going to look something like this.
00:53:32 Let me prep the slides right here.
00:53:36 We have the use transition hook as well as the use deferred value hooks.
00:53:43 But before we dive into those, let's take a few minute break because I want everything you've learned so far to kind of just get some time to properly
00:53:52 sit and you can think about it, okay?
00:53:55 So take this time to review what we covered, ask some questions in the chat.
00:53:58 I'll answer them once we're done with a quick break.
00:54:01 And then we can get started with the last segment using the use transition and use deferred value hooks.
00:54:08 And the repository link to the finished application as well as the starter will be in the chat.
00:54:13 So if you want to explore things on your own, I can also share my own App Red credentials and ENVs so you can check it out.
00:54:20 I'll drop them in the chat right away.
00:54:22 So you don't have to necessarily create your own ENVs.
00:54:26 You can just get them from there.
00:54:27 Also, let me know, and please let me know, whether you would have preferred this workshop to have been in a code along type of workshop where you can actually
00:54:39 code along this entire demo with me and learn about it, or are you actually okay with this a bit faster way where you can just watch and maybe take in
00:54:48 some of the things that you would then implement later on on your own?
00:54:52 Which way would you prefer?
00:54:54 You can do an up thumbs up for this way that we did right now, or you can do a thumbs down if you would have preferred to have quote along instead.
00:55:04 Okay, I'm glad to see that most of you like the way that with this workshop went.
00:55:10 Yeah, Jesse said that one good thing about live is usually something goes wrong and hence we see some gotchas as well.
00:55:17 I totally agree.
00:55:18 I haven't had a single live workshop where something didn't go wrong and I'm sure none of you have as well.
00:55:25 It's kind of an unwritten rule in development that if you try to present something live, something will go wrong.
00:55:32 That's Murphy's law, isn't it?
00:55:35 But yeah, it's how it works, I guess.
00:55:38 But with that in mind, let's move over to the last two hooks of the day.
00:55:43 I won't bug you any longer, just two more.
00:55:46 The first one being the use transition hook.
00:55:49 And this is a hook that allows you to mark some state updates as transitions, which are considered less urgent.
00:55:59 That's the thing, more or less urgent.
00:56:03 React will work on these updates without blocking the UI, allowing for smoother user experience during large updates.
00:56:13 So, let's put it in simple words.
00:56:16 A useTransitionHook is a hook that lets you mark some state updates as transitions.
00:56:22 It's used to distinguish between urgent and non-urgent updates in your application.
00:56:29 And you might want to use it when you want to keep the UI responsive during large rendering updates, like switching between pages or applying search filters
00:56:37 to a large list.
00:56:41 The syntax looks something like this.
00:56:44 You call it useTransition, and you get access to the isPendingState, which indicates if a transition is in progress, and this startTransition function,
00:56:56 which you use to wrap your state updates.
00:57:00 So going back to the code, now we can explore what would happen if we implemented a search to our application.
00:57:07 That would look something like this.
00:57:10 I'm going to pull up the demo that I have right here.
00:57:13 And show you how the search looks like, just to get the idea for it.
00:57:17 I'm going to head over to forward slash search.
00:57:20 And you can see that we have a regular search and we also have some filters that filter the confessions right below.
00:57:28 So let's go ahead and implement it together using this hook.
00:57:31 Perfect.
00:57:33 Now to implement this, we can head back over to app.
00:57:38 search and then page.tsx where we're fetching the results server-side using search params.
00:57:47 You can see we're using them right here, search params to get access to the query and the filter.
00:57:53 Now the actual searching is happening within the search component.
00:57:57 So let's head over to the search component and let's implement the use transition hook as well as the actual search transition.
00:58:06 First things first, you already know how to use it.
00:58:09 Instead of just declaring the isPending to false, which is a static variable, we can instead say const isPending as well as startTransition.
00:58:21 And you can get those by saying is equal to useTransition just like so.
00:58:28 Once you have it, I also want you to get access to the router by saying const router is equal to use router because we'll actually implement the search
00:58:40 by using the search parameters, which you can update using the router functionality.
00:58:45 So to implement it, simply head over to our handle search and let's do something like this.
00:58:52 const params is equal to new URL search params to which we can pass the search params.
00:59:00 So we're crafting our URL params.
00:59:03 Next, if a search query exists, in that case, we want to call the params.set query to be equal to the search query state.
00:59:13 Else we can remove that.
00:59:15 So we can say params.delete query.
00:59:20 Finally, once we update it, we want to say router.push.
00:59:27 And we want to go to question mark, params.toString.
00:59:32 So we're simply updating the state.
00:59:35 Nothing new, right?
00:59:36 What we have done right now works something like this.
00:59:40 I type something like test.
00:59:43 Click search and the query of test gets added to the top.
00:59:47 Works just fine, right?
00:59:49 But now we're going to implement use transition.
00:59:53 We can do that simply by wrapping what we have here into the start transition function.
01:00:00 Start transition.
01:00:02 And to it, you can pass the callback function.
01:00:05 And this function will contain everything that we have just created.
01:00:11 So I'll copy it and move it right above.
01:00:18 Now, if we go back and if we try to search for something like test, you can see it works perfectly.
01:00:26 I'll actually explain exactly what this is doing to the state and what's different does it make when we implement our next example,
01:00:34 which is going to be filters as well.
01:00:36 Both the use transition, as well as the use deferred value, which we're going to use for the filters, help make your applications more efficient when you
01:00:45 have large rerenders, which typically block the UI.
01:00:49 This way, nothing will be blocked, not with the search, nor with the filters.
01:00:54 So let me just open up the presentation to explain how the use deferred value hook works.
01:01:03 This hook creates a deferred version of a specific value, which may lag behind.
01:01:12 So as you're typing something, you can think of this as use debounce.
01:01:16 As you're typing, the value will actually lag behind.
01:01:19 So it's useful to prevent expensive re-renders from blocking the UI.
01:01:25 Essentially, you can think of the useDeferredValue as the useDebounce for the UI, specifically in React.
01:01:31 So, let me simplify it.
01:01:34 The useDeferredValue hook is a hook that lets you defer updating a part of the UI.
01:01:41 we use it to keep the UI responsive when dealing with expensive updates.
01:01:46 And you want to use it when you have a value that updates frequently, like a search input or filter, and you want to prioritize more important updates first.
01:01:56 And that's going to look something like this.
01:01:58 Con's deferred value is equal to useDeferredValue, and this value React will update after other values, which are more urgent.
01:02:09 Okay.
01:02:09 So you're basically saying the value that you pass into here, defer it.
01:02:13 It's not super urgent.
01:02:15 So let me show you how we can use it in the code to make our filters non-blocking.
01:02:20 I'll head over to the filter component and here want to implement that hook.
01:02:27 So let's simply use it by saying const deferred filter is equal to use deferred filter or use deferred value coming from react.
01:02:38 And to it, you pass the value which you want to defer.
01:02:41 In this case, the selected filter.
01:02:44 In this case, we don't have just a single click, which we click to submit a specific filter.
01:02:50 Rather, we can keep track of the changes in filters with a useStateComponent.
01:02:55 So I'm going to, sorry, useEffectComponent.
01:02:58 So I'm going to create a useEffect callback right here.
01:03:02 which is going to be recalled whenever one of the things in the dependencies changes, such as the deferred filter, the router,
01:03:12 or the search params.
01:03:13 Whenever something of these changes, we want to recall the function in the use effect.
01:03:18 And here we want to check if the deferred value is not equal to search params that get So if it's not equal to the same filter that we have right now turned on,
01:03:35 then we want to get access to new params because we want to update it, but in a deferred way by saying is equal to new URL search params to which we pass
01:03:46 search params dot to string.
01:03:51 That's going to look something like this.
01:03:54 And then finally, if deferred value exists or deferred filter, then we want to set newparams.setFilter to be the deferred filter.
01:04:05 Else we want to set it to delete it by saying newparams.deleteFilter.
01:04:11 And finally, we just want to call the router.push.
01:04:14 Of course, we want to have the router functionality implemented first.
01:04:18 So let's say const router is equal to the useRouterHook.
01:04:24 So let's say use router coming from next navigation.
01:04:29 So let's properly implement it from here.
01:04:34 And we can now just call the router dot, um, that's going to be push and we want to push to question mark and then new params dot to string.
01:04:47 So we will basically be updating the value of a specific filter.
01:04:54 I can see Jesse said, every time I remove a use effect from our code base, I celebrate a small victory.
01:05:00 I agree.
01:05:01 It's source of infinite extra renderings in many cases, and this code can definitely be improved for sure.
01:05:09 But for now, yeah, it's still used in a lot of code bases and I actually wanted to show how using the deferred filter can help to remove those infinite
01:05:19 extra re-renderings in many cases.
01:05:21 So hopefully, maybe this makes you not remove as many, but just implement the deferred value.
01:05:27 Great.
01:05:28 This was supposed to be deferred filter, actually.
01:05:33 So now that we have that, what do you say that we test out this example to switch between different filters and see how quick it is and how it's not blocking
01:05:41 us or doing that?
01:05:44 Well, let's test it out.
01:05:46 If I go back to the code base and I try clicking different filters, you can see that it works very well.
01:05:58 you can see just how nice it actually updates immediately, right?
01:06:02 Exactly as it's supposed to.
01:06:03 We can also remove this test from here, search for everything, and now we can filter based on different filters.
01:06:11 Super simple.
01:06:13 But to show you the actual difference does it make, I actually want to show you how a filter without using the deferred value would work.
01:06:22 So I will override this code with a regular use effect, or we're not using the deferred filter.
01:06:30 And I'll also head over to AppWrite, head over to the filter confessions, and I will delay the time it takes to fetch the filters by 10 seconds.
01:06:43 So it's super obvious what's happening.
01:06:46 Now get back to the demo and try it out.
01:06:49 I'll reload the page.
01:06:51 And you'll notice that it takes 10 seconds to fetch the initial coffee drip.
01:06:55 My browser even started lagging as you can see.
01:06:58 But now if I click on the second one, it'll start fetching it.
01:07:02 And it seems to be working very well.
01:07:06 But if I switch it over to use the version of the, of the filter, which doesn't have the defer value, let's see how that works.
01:07:18 I'm going to get back to the search.
01:07:21 reload and see if I click rubber duck army it's actually taking 10 seconds but it didn't even update the search like at all it's gonna wait for 10 seconds
01:07:31 to pass and only then will it update the search that is terrible I mean now I click the coding magic wand and then what happens I have to wait 10 seconds
01:07:41 for it to happen without even updating the search.
01:07:45 And what happens if I want to check out multiple?
01:07:47 Well, that's just a mess.
01:07:48 It's going to give me the last one I asked for like five or 10 seconds ago, but not a new one that I clicked.
01:07:55 Now check this out.
01:07:56 If I switch this back over to using the deferred value and get back, I have to reload the page on the search.
01:08:04 If I click it, it's going to take some time to actually get it, but then all the other ones will automatically work.
01:08:13 Let's wait for the first one to work.
01:08:17 If I head back over to the filter, we're using the deferred value.
01:08:23 You can see that it changed the filter to rubber duck army.
01:08:27 And it should automatically change the updated filter or change the URL whenever I click some of the next ones without having to wait 10 seconds to do that.
01:08:39 This is something that I want you to explore right now.
01:08:42 It seems like it's not doing it right now.
01:08:43 Is it possible that I didn't save a file?
01:08:47 Let me remove this delay right here.
01:08:50 The whole goal of the deferred value is.
01:08:55 to fetch them without waiting.
01:08:57 I mean, now I remove the delay, so it's actually fetching it.
01:09:01 But the goal is that even without waiting, if this action takes 10 seconds, if you reload the page, it should patch it automatically.
01:09:09 It should start fetching automatically no matter which one you click.
01:09:12 And you can see that right now it is doing exactly that.
01:09:15 The URL changes even before the data updates.
01:09:19 So that's great.
01:09:20 It works.
01:09:23 Hopefully that makes sense.
01:09:25 We explored a lot of different cooks.
01:09:27 We came all the way from just the simple page right here, where we were on the homepage.
01:09:35 So let's get to that.
01:09:38 Where we had a basic form.
01:09:40 Then after that, we had a server form, right?
01:09:43 Under forms.
01:09:45 After that, we have a use action form and a use form status form.
01:09:49 And then later we also implemented the discover page.
01:09:53 which contained the use optimistic form to which we can pass an unresolved promise.
01:09:59 And finally, we also explored two additional hooks.
01:10:03 One for the search, which was the use transition, which allows us to postpone specific actions and say that they're not super urgent.
01:10:15 And then we also explored one in the filter, which is the deferred value one, which is the one that we have seen at the end.
01:10:24 Yeah, so that's a lot of hooks.
01:10:26 And hopefully you were able to see, and you now have a clear picture, how to manage forms more efficiently, how to handle validation,
01:10:35 and improve both performance and user experience.
01:10:38 Remember, it's a balancing act of whether you want to display something on the server or on the client side, and learning these concepts takes some practice.
01:10:48 It's more so an art than a science in a way.
01:10:51 You have to practice a bit, see how it behaves in a couple of code bases, see how your builds behave on server side, start small,
01:11:01 experiment, and just revisit what we covered today.
01:11:05 And with that in mind, thank you for your time and your energy today.
01:11:10 It's been absolutely fun to share all of this with you.
01:11:13 And if you have any questions or want to dive deeper into anything, feel free to reach out.
01:11:18 You can do that on LinkedIn, YouTube, whichever platform you prefer.
01:11:22 I'm here and that's about it.
01:11:26 I'll be waiting for your questions.
01:11:27 Feel free to shoot me an email as well.
01:11:29 You can just do that on contact at jsmastery.pro.
01:11:34 I'll see you there or just on the JS Mastery Pro website.
01:11:38 Thank you so much for your time and I hope you enjoyed it and I'll see you in the next one.
01:11:43 Have a wonderful day.