Channel
Interviewed Person
Aurora Scharff
[Music] This conference is brought to you by Callstack, your React and React Native development experts. [Music]
Hello everyone. Uh, my name is Aurora. I'm a web developer from Norway and I work as a consultant at Cran Consulting in Oslo. And um, I'm excited to be here to be speaking about modern React patterns, concurrent rendering actions, and what's next. Um, I'm actually not a native developer, but I'm really happy to be here and update you guys on what's happening on the web side of things. So, handling async operations in UI components can be tricky. We might encounter flickering pending states, inefficient state updates, and unstable user experiences, and overall excess complexity. And with React 18, we uh got concurrent rendering, which allowed us to improve the responsiveness and UX of our apps already. And now in 19 we have even more tools at at our disposal and new ways to combine them. So uh these are the concurrent features we are going to explore today. Sorry. Uh use transition, use optimistic and use deferred value and they are going to become increasingly more important with
view transitions coming to react which we are also going to see at the end. So who here has ever used use transition? Can I see how many people have used that? Okay. Hey, what about use optimistic? What about use deferred value? Okay, nice. And who has tried the experimental release of view transitions in React? That's that's very impressive. So yeah, uh great. Let's begin and dive deeper into these features. So uh I have here a um some selects for uh years tags conf uh speakers and conferences. And let's just see the UX of this. So um when I click one of these selects you'll see I have kind of a delay in the select. Uh I can try that again. So I'm clicking and then it feels kind of stuck. It's not updating instantly. And if I click multiple for example AI and Angular I get this sort of premature loading state. So it's it's you know it's not exactly how it's supposed to be. And this also this also does like a flicker here. So clearly I have some UX problems in the
select. Let's see the code and check out how this has been implemented. Um so the the selects are implemented by this async select component. And looking at the code it's written in the most common way that people write react code today. Yeah. I have here a selected state. Then I have a select with an unselect event. We have uh this async function execute async work getting the results setting it as a selected value and then I'm also managing the loading state here setting it to true and then finally setting it to false. So looking at this code I'm able to identify the problems or the cause of the UX problems. So this one is pretty clear. When we wait for the result of course the select is not going to update until the result is done. So that one's uh makes a lot of sense. But for the flicker uh the reason that's happening is because I have this um I'm managing my loading state with this shared uh var state here. Which means that whichever async call finishes first is going to
overwrite uh the previous state and then we get this premature loading state that we saw earlier. And that's also uh the reason that we get that weird flicker on the selected value. So the fundamental issue here is that the browser does not natively support async events or coordinating work across async events and I need a way to um uh handle as m handle the work as multiple things are clicked and then once they're all done uh set the states uh in a batch. Fortunately, React has an API for this transitions. Transitions allow us to coordinate async work across events and render. Uh so let's see how we can use transitions here to improve the UX and avoid those flickering states. So I'm going to uh import here use transition and use transition all uh returns a pending flag and a function to start a transition. And start transition will mark some sort of uh group of state dates and async work as deferred or lower priority. So, I'm going to wrap this around my uh async work here.
Let's just wrap it all the way down. And um since we are in React 19, we can use async transitions like this and just move the async flag. And then I don't need need my uh manual loading state anymore. I can just use this one and remove all of this uh manual work here like that. And uh we also need to wrap additional state updates after an async function in a transition. But this is going to change in the future. So let's do another start transition here. Um yeah, we're not going to be able to we're not going to need this in the future. So what I'm actually doing here is creating what's called an action. And that's just terminology for a function called in a transition. Um let's try this out. So now when I uh select these values, one is just the same behavior but selecting now multiple you'll see the loading state is entirely in sync until the whole interaction is done. So one, two, and then it's just persisting until executing everything at the end. So we
don't have any more flickering problems. So that's one thing fixed, but I still have this problem of uh the uh select not updating right away. So I need some sort of optimistic update for this. And we could do it ourselves and set the selected value, roll it back, all of that. But instead, let's use optimistic for this. So we can get the use optimistic hook. And this hook works alongside actions and takes in a state to show when no action is pending, which can be our selected value here. Um, and then it returns uh a optimistic selected value and then also a trigger function. And we can call this trigger function uh in the transition we want to coordinate with. So that's just this one over here. Then use the optimistic selected value as our selected values. And the way this works is that for as long as the transition is running, we have this temporary optimistic state that just is uh settles to the past state once the transitions are done. And that means that our interaction will
look like this. So we have this instant uh optimistic update entirely in sync with the loader here and it becomes a bit clear if we actually reject this promise and see what it looks like then. So let me reject this and then I'll just comment out the toast and uh let's see that. So now when I click I still have this optimistic update but it just falls back to this past value because the past value didn't match anymore. So it's like an automatic roll back. So now we have actually fixed all of our UX problems. Uh let's see this again. And we have this very smooth interaction. No flickering states. Yeah, that's just a toast. That's okay, right? Um so what is this app anyway? Let's see what's inside this app. This is actually a uh Next.js JS app router app and um I'm using I have set it up with Prisma as my OM and Prisma Postgress database and right now we were only looking at the filters but there is a couple more things inside this app. So let me just