What's New in React 19 And How to Use It

In this talk, Om Gate, a full-stack developer, explores the new features introduced in React 19, highlighting improvements in performance, efficiency, and developer experience.
React Compiler:
Optimizes code by eliminating unnecessary re-renders and computations, automating optimizations that were previously manual (e.g., useMemo, memo).
Server Components:
React 19 introduces Server Components, which enhance server-side rendering (SSR) by separating client and server rendering. Server components are rendered on the server and sent as a streamable data payload, reducing the time to interactivity and improving performance.
Server Functions:
Server Functions allow for secure, server-side operations like authentication without exposing sensitive logic to the client. This keeps the client-side experience faster and more secure.
React 19 brings several powerful enhancements, making apps more efficient and easier to develop, with a focus on automatic optimization and a better balance between server and client-side rendering.
Share this talk
Transcript
Hello. My name is Ohm and I welcome you all to this session about what's new in React 19 and how to use it. In this session, we are going to dive into all the cool stuff which has been added into React 19 and we are also going to see how to make the best use of it.
So, a quick little introduction of mine. My name is Om. I am a full stack developer currently interning at VideoDB. And, let me tell you, I love frontend. Frontend is how I got started with full stack development and such.
And, like most of, like most of us, even my, library well, my first library which I worked with for this was React. Now React is our, UI library which helps us build user interfaces. And when we talk about React, we are mostly talking about three of its properties, especially for this session.
These three are the most important one. First one is its declarative nature, meaning that, react in React, we define how the UI state would look like, and React will handle how to make it happen.
React is component based, meaning that instead of writing entire pages, in one go, we write these modular components, reusable components, which we can use here and there everywhere making our job much more easier. And at the same time, React is efficient with its own reconciliation and virtual DOM stuff.
It makes it so that if we have some really expensive, really complex application, they work, even on that. Even if we have some complex state updates, it works, really, really fast.
So when we talk about, all the features which has been added into React 19, Each of these features sort of push React into these directions, wherein something is making React more declarative, it is making React more efficient, or it is making it so that we can write components much more easily.
So that's going to be a really common theme amongst all the features which have been added in React 19. And so let's begin with React Compiler, which is going to be the first topic we are going to study about.
And so what React Compiler does is that it optimizes our code for us, wherein, it eliminates all the unnecessary rerenders and computations which happens due to the intrinsic nature of React.
So the nature of React which I'm talking about is whenever a state or a prop value changes in a React component, what React does, it re renders the entire component, meaning all the JavaScript code we have written in the component and all the JSX inside of it, all the components rather inside of it, are re rendered.
So, what I have over here is a particular form component. And inside the form component, I have the same name, email, password form. And since, the password all these states are changed on change, meaning on every single keystroke, these components will are going to be rerendered. So whenever I type in something, the form is getting rerendered.
But the problem is that name, email, password, all things are getting rerendered. And so if you want to avoid this, by the way, the way we would need to do it is by,
like, attaching it to a particular higher order component called as memo. So what memo does is it tells React that, hey. I have a component. And until and unless its state values are the same, they don't change. Do not rerender it even if its parent has rerendered.
So even the now what happens is even now, wherein, our form component is rerendered, meaning that all these components side of it should also rerender.
Since we have memo in this input component, since its props have not changed, the input component is also not rerendered, meaning that the email and password have not rerendered even if we have changed the name. And precisely these are the optimizations we have to do. We have the useMemo for values, useCallback for functions, and memo for components.
But the problem with all of this is that these all things are manual optimizations, meaning that for just a simple calculation, we have to hook it on to this particular hook. We have to pass in dependencies and stuff.
And if we mess these up, like, we can write some wrong dependencies and stuff so we can have some issues. Like, stale updates and, maybe even unnecessary computations again, meaning that these things are really tough to maintain.
And that's why we have React compiler, which, what it does is, it takes our code And instead of generating the final JavaScript, which basically is the flow which we have with Babel, it takes our code and it optimizes it for us. And without us needing to use these, hooks.
And what it does is, it is it takes the it groups all these values. It groups our components, functions, and values together, and it creates some reactive scopes. Now reactive scopes are these values which are sort of created and mutated together. So what it says is that, hey.
In this code, I have this particular scope with the form component and the first input component. Under this reactive scope, meaning that if the name value changes, only rerender these two components. Same for email, wherein if I have the email component, let's rerender only the form and the first input component. And same thing for password.
Meaning, in the React code, since it is already being optimized, if you go to the React compile code, you can see that I do not have any memo.
But even then, if I go ahead and write the name, without any optimization, since it has created a React to scope, around the form component and only the first input component, we don't even have to do anything with memo. React has already optimized it.
Meaning, if I again change the email and if I change the password, the re renders happen, really in an optimized manner. So now our code is now really optimized. We don't have to use any hooks.
And with the help of these reactive scopes, React really knows which components to, render, update and which not to when a particular state updates. And now what it returns is an optimized code, which is an optimized version of R code, which basically will do it for us.
So, gone are the days where we need those hooks of useMemo, useCallback and higher order memo component. And so now let's move on to the next optimization we have, that is of React server components. And what React server component do is that, it makes it so that our server side rendering is much more efficient.
And so, let's talk about server side rendering first. So in server side rendering, we know that what we do is instead of, whenever a user requests a page, you're rendering the React code on the browser by sending it to JavaScript. We render the JavaScript.
We render the entire React tree on the server itself and generate the HTML out of it. Meaning, we render the header. We render the sidebar. We render the main content. We render the footer. And the moment the entire HTML has been rendered, we send it to the browser.
We send the entire JavaScript of it too, meaning that, whatever React code we have, the JavaScript bundle of it, we send it. The reason of it is because we have some interactivity. We might have some states. We might have some effects we have to want.
And since that cannot be done on the browser itself, we send the JavaScript code for it and we do something called as hydration. Hydration basically is a process wherein we take the HTML and we apply the all the required JavaScript of it, which has been said in the React code. Now this is great for optimization of SEO.
It is great for user experience. But it has its own flaws. The flaws are if the rendering of it takes time, so this entire page, let's say if it is bulky, the, initial load time is highly, it increases. So there's a fraction of second delay.
Some applications, which I have seen have, like, delay of two hundred, three hundred milliseconds. So that is really not that great. And that is because since we have to wait for each and every component, like, if the header is not ready, we can't show it because we have to wait for the entire component to load.
So what users see is a split second blind screen, which really is not a great experience. And since, we have to send the entire JavaScript bundle for hydration, hydration process itself takes long time because with JavaScript to first load and then run, it takes some time. So the time to interactivity is also hampered.
So then what we do is what we say is that instead of doing everything for every other component, we divide them into two types of components, that is server components and client components. So what we say is that there are some components whose output is only HTML. There's no JavaScript attached to it. There's no interactions and stuff.
While we have client components, which can only run on the browser, which are like, buttons and forms. So what we say is that let server components be only rendered on the server, and we just display it as and when, they are rendered.
And whenever we have client components which have to and, support these interactivity states and effects, we'll, run them on only on the browser. And not only just only on the browser. We'll obviously render something on the server itself, but we'll, basically hydrate it, on the browser itself, but only those components.
So now what we do is that we whenever a user requests a page, instead of generating the HTML, we take each and every component. We take the header, let's say. And instead of generating the HTML, we create something called as a RAC payload. And this RAC payload is not HTML. It is some JSON type, streamable data.
I said type. It's not actually JSON. And what it does is that the moment header is ready, we generate a payload which has all the information required to render this header. And since we stream it beforehand, if the header component is ready, we don't wait for every other component. We just display that.
Same for sidebar, same for footer. And since, like, we saw that we have server and client components, let's say, if I have a client component like a form, we what we do is we generate the placeholder of it. Let's say, the initial state of that.
Maybe you have added a loader or something, but if not, then it might just have a basic initial state. We'll just render that and display it. And we'll send the JavaScript related to the client component to the browser so that, that component can be hydrated on its own.
Meaning now what has happened is, we have improved the first contentful paint over here since we are streaming each and every component. What we are doing now is that the components are now being, incrementally displayed. So first content full paint has improved.
Since we are only sending JavaScript for client components, the entire process of, hydration and all has improved. So JavaScript load already has improved, but also the performance has improved. Time to interactivity has improved.
And so now what we have is the best of both worlds wherein we not only have improved the speed, we have not only improved the, we have not only improved the time to interactivity, but all the SEO and user experience related stuff still persists. And now SSR has become really, really great solution.
And now we move on to from this whole React server components. And I'm telling you that if you're someone who works with, SSR, by the way, all the examples which I have given over here, like, over here that for SSR are all of Next. Js. This is all the Next. Js flow.
But if you want to look at any other things, please, I'll encourage you to look into more about React server components. But when we are talking about server functions, they are somewhat like server components.
But instead of, functions which run on the client, meaning this function being sent to the client, these functions instead stay on the server and run on the server. So, let me tell you how they look like. So, what I have over here is a Form Action component.
Inside of this component, if I shorten this window over here, I have an email and password page. So we can see the components over here. And I have passed in an action, which is a server component. And the way we declare server component is by this use server directive, which we can write.
And what it is doing is it is complete it is doing a particular email check. So it is basically doing an auth check for email and password. This is currently something which I have done for, demo proposal, but feel free to add in your database and stuff. So over here, we'll go your database.
And what I have done is if I click sign in, I have added this data. And now if I click sign in, something interesting is going to happen. So the moment I click sign in, instead of anything being run on the console, something runs on the network tab.
And you can see, instead of the code being run on the client, we make a post request to this page. And inside of this post request, this, credential check was done. You can see the payload. The payload was, overwind the password, which was the wrong one.
And instead of this, function being run on the server wherein it would have console dot logged out it on the, console in the browser console, it has logged it onto the server, and it has handled the particular state wherein we redirect to the page with this error state and has displayed the error for us.
Now, server functions are really cool since what we can do now is our authentication code over here can be with our auth provider or our database without us worrying about exposing it to the client.
And so if we let's say, now this is great for redirections and stuff when we are maintaining, the state via a URL wherein it's fine. But let's say if we want to maintain state, then we can make use of the use action state, which will help us manage the state and the submission status of the particular action.
Now over here, what I have is another component and which is, the same component with, with which is the same component. Let me just go to the same page for this one, which is the use action state.
And now with the use action state, in the form action which I have, which is sign in action, instead of redirecting, what we are doing is we are sending some data. Mostly, what you'll do is if you have some forms and stuff, instead of redirecting to a particular page, you would rather, return some data.
So what this action state does is it takes in our action, and it maintains the state output state of it and the pending state of it as well. So earlier, we used to have these two as a diffuse use state, declarations for maintaining these states.
Now with the use action state, you can maintain the output state and pending two. It returns us the form action, which is the, which is the action which we can use so that React is also able to maintain the state and is pending.
So now what happens is if you go to the network, and if I add in the name, let's say mine, and if I write in the correct password now, if I hit sign in, we see that, yes, we are seeing the pending with the help of pending state. And another function call was being made to the server.
We can see correct credentials were passed. Again, it is the post request to the same exact page. And if I see in the payload, yes, my name and password were sent. And in the response, I do see the actual output of the message.
And now if you have anything like, for example, any database call or something which we have to do, we can directly add it over here. Meaning that you don't have to make a fetch request. You don't have to make an HTTP endpoint. This will work just the same.
And now we have written this whole code for, handling server functions. But let's see about the what about the components.
So use form status is going to help us manage the submission status of this function, of this component of these forms, meaning that a component will be able to read the submission status of other particular parent form without needing it as a prop.
So over here, I have a button component, and you can see that there is no prop being passed. But even then, it is able to, sort of taking the, pending state easily. So now what it does is the use form status basically looks at the parent form component. So the parent form component is this one.
And whenever its action is running, it will basically take in this state, and it is going to say, hey. This code has to be,
if the form action is actually, running currently, this pending would be true. Otherwise, it would be false. And that way, we would be able to handle this state without ever being passed as a prop.
Now you can see there is a huge boost given to the forms and, the way we maintain state from forms and the components related to it, meaning that if you have anything related to forms and stuff, you have to maintain it with these input times and all.
Please do get, take a look at this and try it out. It's really cool. And now we move on to our last hook, which is the use optimistic hook. And what use optimistic hook does for us is that it, up manage it manages optimistic UI updates.
And what you optimistic UI updates are, basically, these are the UI updates which you do optimistically to a server response wherein you update the UI before we get a response from the server itself. So what I have over here is
to do list application. And let me just show it to you over here as well. So I have a no optimistic page, instead of which there's a to do list.
It's a simple to do list, which if I write something over here like do homework, and if I add task, it is going to run run the handle add task. It is going to make an API call.
And after like five odd seconds, it is after the API call has been done that is, it shows us the list. Now this is great. This is how this to do list application can be. This is the easiest form of it.
But if you look at the lens of a user experience perspective, you would notice that this delay between clicking the button and it actually showing is really bad user experience. And so the way we would like it to be would be that, hey.
If I have written something like do homework over here, why should why can't it just update it automatically? The moment I click it, if it shows over here directly, that would be really good user experience. And that is basically what the optimistic UI updates are wherein when we click it, it will update it automatically.
So let me show you a demo for it. So what I have over here is an optimistic state. And if I add in, let's say, do homework, you can see automatically the particular state has been added. But notice something cool.
After a certain time, you would see the actual task has been gotten and the ID has actually changed. So what is that? Well, let me tell you what optimistic state is. So what we do is, the way you handle optimistic UI updates over here is you use the use optimistic hook.
And inside the use optimistic hook, you pass in the state. So I want to optimistically handle the task list. So we take the task list and we pass it to the use optimistic hook. And what we do is, we instead of showing the actual task list, we are rendering the optimistic one.
And now what React does is that, it latches on the value of optimistic task to the real task at all times. So you can see that currently the actual task, which I'm logging over here, is actually, having only one task with the name do homework. Correct? And password starting with d forty eight, which is correct.
So it is basically clearly maintaining the actual task list.
But what happens is the moment we are running the handle add task function, which basically any action, So this works the state updates optimistic state updates only work under transition and action because React has to have the control over or to knowledge of when a particular update is happening.
It does it with the help of actions and transitions. So when we add something like bring groceries, what it does is what we are doing over here is we are making an optimistic task. Basically, what a task would look like if we get it from a server. And we update the optimistic task list.
Meaning now what happens is React is now going to display a particular list like this, with the actual task and the optimistic task attached at the end before we make the API call. So when I hit add, it is going to show the bring groceries one, which has been added optimistically.
And the API call has not been made. It is still an empty list. But once the empty, API call has been made, the task list has been updated, it actually, gives you the actual task list. And React is going to say, hey. Hey. Since I have the actual task list, I'm going to show the real phone.
So to summarize all of this, what, React does over here is that it says the optimistic tells the optimistic task to listen to the actual one. And whenever inside of a transition, we, update it or in an action, it shows the optimistic list. And when it starts showing it, then we make the request to the API call.
So we have already updated the UI accordingly, and we have now making the API call. And the moment we get the actual list, we then transition or we show the transition and the then we, update the actual list, then we, conclude the action. We conclude the transition.
And the moment the transition is over, React is going to say optimistic state. We have the updated actual task. No need to show the optimistic one. Show the real one. So this whole, switching between the actual and optimistic thing is done is handled with React on its own.
So it's a really, really powerful, a hook which helps us managing a really, really good UI user experience status. So definitely do check this one out too. Now let's move on to our next, not a hook, an API. And, it's a really, really good one. I really love this one, and that is the use API.
Now this use API is an API which helps us to read resources like promises, and, it would basically reach promises and context for now. And what it does is whenever it is, resolving, takes in the promise, it resolves the promise, and it suspends the component on its own.
Meaning that now, fetching anything from APIs or resolving any promises inside components is really, really easy. So over here, I have the use component. And what I have over here is that I have an error and suspense boundary, and I have a, context, which is basically a theme context. So now if I go to this particular
example, you can see that
what I'm doing is I'm making an API call to this users list. I'm getting the users list and I'm displaying it. So the moment I reload it, you can see the list of the users have been shown. And when I'm loading it, the suspend boundary is triggered.
And that is all because I'm, calling this API with the help of use. So now what it is doing is it is automatically suspending the component while it is trying to resolve it. At the moment it resolves it, it puts it into this users list. And at the same time, use API can also do something cool.
And that is it since it is reading a lot of resources, it is sort of supposed to do many tasks at once. So it can also handle context. So it works just like use context. Meaning, it can consume a context, and it will return you the values, and it will handle the context updates for you.
This is a really cool, API, which is also since it's an API, it's not a hook. You can conditionally use it, meaning that this very well could have been inside of an if statement wherein we could have said, hey. Do I want to only fetch the admin users or all the users and stuff?
And if we do it inside an if statement, it works still fine.
And so, if we have any complex, cases of, like, a conditional calling of promises and stuff, which we were not being able to do well with the earlier stack, let's say, with use effects and stuff, well, that is if you are not using promise, suspense and all, this has become a lot more easier.
So, I really hope we get even more powerful stuff added to use. But for now, what it does with promises and context, it's really awesome. And let's meet our last part that is support for document metadata.
So metadata is basically all these values which are inside our head components such as title and links and meta components itself like og description and title. And since, yeah, the way React works, we cannot really update these in the head. We use some libraries or we, like React helmet or we do it with Tom.
But now support for these components has been added into React. So we can do some pretty cool stuff. And And let me just show you that particular side of cool stuff. So I have over here a meta page, and the meta page works just like Twitter or any other page.
So over here, what we have is I have certain notifications. Let's say, in Twitter and something, what happens is if you have notifications, you show the number of notifications in a bracket. And let's say, if I consume the notification, then they go to zero. Yes. Now they are removed and I can see the title.
If I get one notification, I will have that. If I have 10, automatically the title updates. And the code for it is actually pretty simple. And the code for it is basically I'm checking if the notifications are greater than zero and I'm directly updating the title here. There's no strings attached.
There's no head component which I have written over here. It's directly updating the title here itself. Meaning, the, I don't have to use any, directories like React element. I don't have to use something like DOM. I can directly do it over here. The code has become much more cleaner, declarative, and so much easier to work with.
If you have any use cases related to document metadata, please do check this out. It is really awesome what React has brought in over here, and I'm really excited about all the new things which has like, this whole shackle being broken, related to document metadata. And I'll call it a wrap.
There's multiple things which has been added, lots of improvements, lots of supports, lots of the, things here and there. And I've condensed it for the all the important stuff which we have to worry about. But let's say if you want to search for this, I will highly recommend you for going through all of them.
And if you want to go through all of them, I have all these references and resources for it. So please go ahead and check it out. It's really cool. You can go through all the, compiled stuff here if you want to go through my code. You can check it out in this link over here for GitHub.
You can check all the source code which we have discussed today. And until then, thank you. Thank you all for being here. Thank you all for sticking out and, sticking around till the end. And if you have anything, any feedback, if you want to discuss anything related to React 19, please do connect with me in the socials.
I would be eager to communicate with you related to this. I'm really, really excited to see where React 19 is going as well. So let's see. More power to React. More power to you. And thank you all for being here. Bye.