Rendering: To Sync or Not to Sync?

Rate this content
Bookmark

Let’s dive deep into React rendering and evaluate the implication of Concurrent Rendering and automated batching on code that previously relied on the synchronous nature of v17. Does it always make things better? With a real world case study, we evaluate useSyncExternalStore and flushSync as tools to restore synchronous rendering to avoid “visual tearing”. Working through the trade-offs of these approaches will give us new insights into React rendering and hints on how we can optimise our applications.

28 min
13 Nov, 2023

Comments

Sign in or register to post your comment.

Video Summary and Transcription

This Talk discusses rendering and synchronization in React 18. It addresses issues such as flashing rows and wiping out when scrolling. The use of usync-externalstore for concurrent reads and the potential misuse of APIs are explored. Debugging techniques using React Profiler and flush-sync are discussed. The talk also covers performance considerations for different machines and the importance of testing and considering alternative solutions.

Available in Español

1. Introduction to Rendering and Sync

Short description:

Today I want to talk to you about rendering and whether we're going to sync or not sync. We're going to have to try and work out what is going on. The first bug we're gonna look at is clicking the scroll bar causes this flash. The second issue we've got is when you're scrolling, they're completely wiping out. We've upgraded to version 18 and switch to CreateRoot, enabling concurrent rendering features and automatic batching. Let's look at the code which is causing the updates for the road, and there's nothing exciting here. But I think there's some prime suspects for this issue in version 18, concurrent rendering and automated batching.

♪♪ Today I want to talk to you about rendering and whether we're going to sync or not sync. There was a funny typo when this first got shared on Twitter, where it was actually S-I-N-K, and I was thinking, oh no, is that what they're predicting my talk to be? But let's hope not. So, to sync or not to sync? Let's dive into this. It should be hopefully be an easy question to answer.

Which of these grids is better? So, on the left, we've got Agigrid running in version 17 of React, where you've got this nice, smooth scrolling, you can click the scroll bar, and the rows just appear in the right place. But then you upgrade to version 18. So, this isn't a live version of Agigrid, this is an older version which had this issue. You click the scroll bar and the rows flash, or you start scrolling up and down and the rows blank out. And it's like, as you can tell, this is not what we want the user experience to be. So, we're going to have to try and work out what is going on.

So, as you know, I'm Steve, and I do work at Agigrid, I'm on the core grid team. And so, Agigrid is what we're trying to do is create the best JavaScript data table, whether that's in React or any of the other frameworks. It's a free tier as well as the Enterprise, and if you want to find out more, do come speak to us at the booth. We'd love to talk to you about all of it. But enough about that, let's try and clarify what we're trying to fix and how React has changed, how we can try and work out what those changes are, and then how we can fix it.

The first bug we're gonna look at is clicking the scroll bar causes this flash. Let's see, can you see that? Yes. And then, the second issue we've got is when you're scrolling, they're completely wiping out. Okay, and so, this is the only line of code which is different between those two examples. So, we've upgraded to version 18, and then we switch to CreateRoot. So, when you're using render, it's the equivalent, basically, of the rendering from version 17, but now with version 18, switch to CreateRoot, and then you're gonna start enabling all these concurrent rendering features and automatic batching. And so, that's what we're gonna do. We're gonna go bug hunting.

The first thing to do is, well, let's look at the code which is causing the updates for the road, and there's nothing exciting here. It's just state. So, when the road's changing, you scroll and you need to look at new roads. We're gonna update which roads are displayed. So, there's nothing really, I mean, unusual there, or complicated, or anything that should be going wrong. But I think there's some prime suspects for this issue in version 18, concurrent rendering and also automated batching. And what we're gonna do is, and see if it's these two features which are now interacting negatively with Aggrid's row virtualization.

2. Row Virtualization and Rendering Changes

Short description:

Row virtualization is a critical performance feature for data grids. Rendering only the visible rows in the viewport prevents overloading the browser. In version 18, there is a flash issue due to changes in rendering, which now has priority-based instructions. These changes, while enabling features like useTransition, can have side effects. Check the React GitHub discussion groups for more details and context. Ivan's talk is also recommended for further understanding.

So, I guess, first of all, what is row virtualization? This is a critical performance feature for any data grid. If you want to show thousands and thousands of rows, you don't want to have to render all of that out in HTML, because you're gonna crash your browser and the experience is gonna be really, I guess, slow and difficult. But the main thing is, you don't want to overload the browser because drawing HTML is quite expensive.

So, what we're gonna do is we only render the rows that are actually visible in the viewport. So, here we go. So, a way to imagine the scrolling is we scroll, the viewport changes, and then at this point, if the browser gets to repaint, it's gonna repaint an empty grid, because the rows haven't been updated yet. And then the rows get updated after we've based on the new position of the viewport. So, I think what we can kind of imagine that's happening is that the rows aren't being updated quick enough, as well as the viewport. And so, another way we can look at this is in the DevTools profile.

So, in version 17, we'll take this benchmark of this action where we scroll and update the viewport. And the main thing to take away from this chart is that there's a single function call, and then the browser paints. So, what that represents is it's scrolling, changing where the viewport is, and rendering the rows all synchronously, and then the browser is painting. So, you don't get any kind of flash. And if we do the same thing now with version 18, it should be quite apparent where this flash is coming from, or the result of that break. So, the scroll happens, then the browser is actually getting a chance to repaint, which is why we're now getting this empty set of rows before the rows are then rendered. So, we're getting two paints instead of one. There we go. And so, this is something that we need to be aware of in version 18. So, rendering is no longer a just purely sequential set of instructions. But there's priority-based in it. And a lot of the new features in React, they require the rendering to be interruptible and support yielding to the browser. So, useTransition is a great example of this. So, it's letting you update state without blocking the UI. But these changes in the rendering have some side effects and we've run into them here in this situation. So, I'm not gonna go deeper into all of the concurrent rendering and all of that stuff. There's a lot of good information you can get on the, both on the React, GitHub discussion groups. There's so many good nuggets of information in there in the comments and in the responses. So, if you haven't looked at these discussions before, that's definitely somewhere I would say, take a look if you want to get some more low-level details or just context behind some of these changes. Another great tool is from Ivan and he's got another talk later on today. So, I'd recommend listening to him because this one definitely helps explain a lot of these concepts.

3. Using usync-externalstore for Concurrent Reads

Short description:

We'll start with usync-externalstore, a way to support concurrent reads by forcing synchronous updates from a store. Visual tearing occurs when React yields during rendering, allowing the external store to update. In version 18, this can result in the display of conflicting colors. To use useSync external store, you need a subscription method and a snapshot method. The subscription method sets up a callback to notify React of store updates, while the snapshot method provides an immutable state of the store for consistent rendering.

Right, but then back to the issue, we've still got to solve this bug because we can't ship this product in the state that it was in. So, in the documentation, there's two features which contain the word sync. We could just start there.

So, there's usync-externalstore and also flush-sync. So, we'll start with usync-externalstore to start with. So, usync-externalstore, as the name suggests, is a way for you to support concurrent reads by forcing updates from a store to be synchronous. And this is all to do with visual tearing, which is the term.

So, the way to visualize this or imagine this, this is from one of the discussion groups, is that say the child knows that they're getting their color based from an external store. So, the first one gets to render and the store says you should be blue. And then React is now yielded, because this is part of the new way that we can have interruptable rendering, which has given the external store the chance to run an update and to now say that the color should be red. So, in version 17, this wasn't a problem because React was not yielding, so the store could not have updated until React had finished all of its rendering. But now, in version 18, because React is yielding during its rendering, the external store is actually getting a chance to run an update, so then, rendering is then continued and it's now picking up the color red. So, the fact that we've seen blue and red displayed at the same time is called a visual tear. So, that's something which maybe isn't happening in our situation, or maybe it is. Sorry.

So, how do you use useSync external store? Well, there's two parts to it. You need a subscription method and also a snapshot method. So, the way this works is, you need to, I need to turn that off. One second. There we go. I'm not sure which one that was. The subscription is a way of setting up a callback to say, I'm gonna take this function from React, so that's the state changed, and I'm gonna subscribe it to my store. So, when rows are changed, I can then call that function to tell React that something has updated in my store. And so, when that has then happened, React is then gonna call your snapshot method. And the snapshot method has to return an immutable state of your store so that React can then use that snapshot and complete its rendering from there. So, this is the way that instead of React keep coming back to the store during the rendering, it just returns the snapshot and then uses that consistently. So, then, even if your store updates, React will then see that it's had this state changed method called, and it will go back and get a new snapshot and restart the rendering instead of rendering halfway through and have the tearing. So, that's how this hook works. You say, using external store, pass it the subscription method and also the snapshot. And then you can use it like state, like in your controller and just map over them.

4. Rendering Synchronously and Potential API Misuse

Short description:

The big change is that the rendering is now done synchronously, which fixes the first bug of flashing rows when clicking the viewport. However, the second bug of continuous flashing when scrolling remains. We're potentially using the wrong API without an external store, but let's continue for now.

But then the big change is that this is now done synchronously. So, does it work? Well, yeah, it does. It fixes our first bug. So, now you can click and the rows are not flashing as the viewport was changed. And we can validate this within the profiler. So, once again, we've got this single function, where we're scrolling the viewport and updating the rows that are rendered before the browser has a chance to paint, so which is why that flash is now gone. So, this is kind of looking good. So, we fixed the first bug, but what about the second one? When scrolling, are we gonna get this continuous flashing of rows? And also, it's worth noting here that we don't really have an external store. So, we're potentially using the wrong API here, because all we're updating is state and we're not having our rows, I guess, change as a set during the rendering. So, I think that's something which, you know, you should only use this hook in the right situations. But let's just carry on for now.

5. Debugging with React Profiler and flush-sync

Short description:

When scrolling with use sync external store, there's a slight change in behavior with empty rows appearing. React's automated batching in version 18 significantly reduces the number of renders compared to version 17. However, this breaking change can be mitigated with the opt-out option called flush-sync. By using flush-sync, you can force React to flush updates within a callback, ensuring DOM updates before performing other actions. Be cautious as improper usage can impact app performance. Wrapping state updates in flush-sync can render them synchronously and improve performance. Consider using flush-sync instead of use-sync external store.

So, this is what happens when you start scrolling with use sync external store. It's slightly different behavior. I don't know if you can quite see it, but there's empty rows now. So, previously it was completely whiteing out, but now there's empty rows.

But I think the idea here is something is still not quite right. So, this is where we can reach for another tool and now to debug this and look at the React profiler. So, if we compare the profiles for scrolling, in version 17 we had like over a thousand renders, this is when you do lots of continuous scrolling. But in version 18, it's only 225. So, something is going on that's quite radically changed how React is now rendering this. And that now points us back to our other suspect feature of automated batching.

So, this is an out-of-the-box performance improvement in React 18. So, in version 17, state updates within a event handler were batched, but state updates anywhere else weren't batched together. So, in version 17, this code within the set timeout would result in two renders. So, firstly, it would update the count, React would re-ender, set the flag, it would render again. But in version 18 with automated batching, they're now batched together in the same render and it will only do it once. So, this sounds like a great performance win. And in the majority of applications and situations, this is exactly what we want. We don't want React doing wasted render cycles when it knows within this event, this is everything that has changed. But this is a breaking change, and React, they do note this, that it is a breaking change. And they expect it to be a performance improvement. But they also then handily provided an opt-out called flush-sync. So now we can go and see, well, is this actually what we need to do to solve our problem?

So flush-sync, the idea behind this is it lets you force React to flush the updates that you make within a callback, and so that you can then ensure the DOM is updated before you, I guess, perform any other actions. A common use case for this is input focusing among other things. But then there is a pitfall, so it's saying it could hurt the performance of your app, and this is because we're then opting out of that automatic batching. So whatever you run within this flush-sync callback, you're gonna force the browser to render. So if you do use it in the wrong way, you could hurt the performance of your app.

So this is a way that it can work. You wrap those state updates in flush-sync, and so this one is doing the counter and the flag within the flush-syncs, and it's gonna force React to then render them both synchronously and your batch of the two renders. So let's try this out now in our situation. So instead of the use-sync external store, we can use flush-sync, which is a lot less code.

6. Fixing Extra Updates and Resolving React 18 Issues

Short description:

There's no subscription or snapshots, and we just wrap the set row controllers in flush-sync. Once again, this fixes the first bug because it's forcing that to render synchronously, but then we're still getting this same behavior, so we still haven't got to the bottom of the issue in terms of where is all these extra updates being batched together. So now that's when we can go back to the code and think, well, actually, it's not only telling which rows should be re-rendered, it's also the individual rows where we can say which cells are being rendered. So within a row component, you've got lots of different cells, and that's another part of the state. So when a row is created, it's then gets the cells that it should display and that's another set state. So if we also flush sync at that point in time, then we're saying to React, actually, I want you to render this set of rows, but for every individual row, make sure that you render all those cells and flush those out. So once we do that, we flush across the rows and the cells, we're back to the version 17 kind of performance and experience, and we've resolved the issues that were introduced with React 18, which is great.

There's no subscription or snapshots, and we just wrap the set row controllers in flush-sync. Once again, this fixes the first bug because it's forcing that to render synchronously, but then we're still getting this same behavior, so we still haven't got to the bottom of the issue in terms of where is all these extra updates being batched together, yeah, as it's still only at the 225 and it's not at version 17. So now that's when we can go back to the code and think, well, actually, it's not only telling which rows should be re-rendered, it's also the individual rows where we can say which cells are being rendered. So within a row component, you've got lots of different cells, and that's another part of the state. So when a row is created, it's then gets the cells that it should display and that's another set state. So if we also flush sync at that point in time, then we're saying to React, actually, I want you to render this set of rows, but for every individual row, make sure that you render all those cells and flush those out. So once we do that, we flush across the rows and the cells, we're back to the version 17 kind of performance and experience, and we've resolved the issues that were introduced with React 18, which is great.

7. Rendering Performance on Different Machines

Short description:

Flush Sync results in a better user experience for slower machines by forcing browsers to re-render one row at a time. If the component is running on faster machines, synchronous rendering can be used for better performance. However, it's important to be cautious and consider the specific environment where the application is running.

But another thing, which is a side effect of this, is that it actually really helps on slower machines. So Flush Sync, it results in this better user experience because now we're forcing the browsers to re-render one row at a time. So if our users are on like an underpowered machine, we don't really want them to see what's happening on the right where they scroll and it's just completely blank and they're left wondering, is there any data coming or not. At least on the left, they can see, well, it is taking time, but the data is coming through. So, I mean, this is a very extreme, I've made the render. It just spins for like a couple of seconds before letting React carry on. But it's an idea where we're not always in control of where our component is running. We can't ensure that everyone has a really fast Mac, M2, laptop or anything. So it's important that as a component library, we work to make sure that the default does scale run across all the different places that it might be used. And what about faster machines? Well, if you know that Agigrid is only going to be used on faster machines, you can kind of sidestep all of this and say, yeah, I'm just going to let the rendering be synchronous. Because if your machine is fast enough to be able to keep up with the updates in a way that isn't causing it to block, then you can get really nice performance that way. But you do have to be careful that you know exactly where this application is running, if you're in control, so if you're in an internal company and you know the spec of everything, that might be suitable for you. But it's not the default because it could lead to this blocking.

QnA

Takeaways and Q&A

Short description:

React 18 offers improvements, but check assumptions against your app. Initially excited about batching, but it caused flashing. useExternalStore wasn't the right fit. FlushSync fixed the issue. Consider machine range for performance. For more insights, check my talk on patterns for performance at React Advanced London. Visit Agigrid booth for more info.

So, takeaways. So React 18 does offer a lot of improvements, but you do need to check the assumptions that are being made against your own application. So for us, at first we were excited. We were thinking, OK, batching, that's going to be good. That's going to improve the performance. We're not going to render as much. But then as you can see, it led to these side effects where we're getting this flashing, which is definitely not what we wanted. So we saw we could use the useExternalStore, but it wasn't quite the right fit. And FlushSync was actually the fix that we were looking for. And then also, it's important to consider the wide range of machines that your application or component is going to be run on, and so that you can degrade performance or the rendering appropriately. So if you do want any more insights, I've done another talk on patterns for performance three weeks ago at React Advanced London. And that's another place where we look at, well, how can we avoid renders as well by doing direct style manipulation? So if you do want more insights into what we're doing at Agigrid to make sure the component is as fast as possible, that's another resource you might find interesting. But thanks for listening, and if you want to find out more about Agigrid, do come and see us at the booth. And hopefully you haven't got any too difficult questions for me. Next.

React 18 Upgrade and Debugging

Short description:

From React version 18, there are other benefits besides the rendering change. Upgrading depends on the use case and application needs. Resolving issues and debugging React version 18 can take time. Use DevTools Profiler and React Profiler for insights. Compare output between versions and be methodical in trying out solutions. These are not bugs but changes unlocking new features. Consider the specific application context and the impact on performance. Upgrading may require more work, especially for scrolling through large datasets. Consider the limitations of machines and React's rendering capabilities.

The first one is, from React version 18, isn't it the same as using React version 17? Is there a benefit to using React version 18 if we use the same functions? Yes, well, I think that there's other benefits in React 18 as in just opposed to this change in the rendering, and also it will give you control, in other parts of your application to maybe use features like use deferred value or use transition. So I think you shouldn't block upgrading and thinking that it's not going to work because this is also very much depends on the use case and what your application is doing. So yeah, I wouldn't not upgrade because of this. So the answer is upgrade. Yeah. In short.

The next question is, how long did it take to resolve these issues when upgrading and what general tips or themes can be used to debug React version 18? Yeah, this took me, this took me a while. And I think that's where as well, it was the combination of using the DevTools Profiler as well as the React Profiler to get insights into, well, what's changed. And so there's definitely a lot of comparison of, you know, you could see the output in version 17. Why wasn't it doing the same thing in version 18? And running in development mode, you can then see some of the method names as well in the Profile, which can give you a bit more insight into what's going on. And then, yeah, so then it's just being very methodical with that and trying things out and recording your steps as you go, so that you're not just trying things, changing lots of things at the same time. Because I think, yeah, it's definitely change one thing at a time, see what happens, repeat the process. Sounds good.

The next one is, we're talking about bugs, but these are new features of React. Why are we talking about workaround fixes instead of addressing the underlying code issues? So I wouldn't say this is a bug in React. I would say that this is a change in behavior, which unlocks a lot of new features that React can then do and support. So there's great value in these concurrent features. I think maybe what you, where I can probably give more clarity, is that there's specific kind of things within Agigrid to enable this kind of degradation of performance on slower machines, which then is also interacting with React as well. So it's important to see in your application what is actually happening. Because if you go to the completely synchronous route with rendering, it's all fine, you know, the batching works. But it does mean there's more work for your thing to do. And scrolling through lots of rows of data is an expensive operation. Grids have lots of components in them. So it's pushing the limit of where React can do it based on what machines can also render.

Testing Performance and Throttling in Dev Tools

Short description:

It's important to test performance for slow machines to ensure efficiency. Throttling in dev tools is a good first step, but it may not be completely accurate. Services like BrowserStack allow testing on physical devices virtually. Reach out on Twitter for more information.

So it's important to see in your application what is actually happening. Because if you go to the completely synchronous route with rendering, it's all fine, you know, the batching works. But it does mean there's more work for your thing to do. And scrolling through lots of rows of data is an expensive operation. Grids have lots of components in them. So it's pushing the limit of where React can do it based on what machines can also render. We love an efficiency win, so that's good.

The next one is, how do you test performance for slow machines? So there's a few different ways. There's throttling in your dev tools. I've got some reservations about whether it's completely accurate. But then there's other services out there where you can actually have a URL if you've deployed it somewhere and you can log in and run on physical devices virtually, so that's quite a useful way of then getting a real feel for it, because I'm not sure the Chrome DevTools or the other ones when you're doing that throttling is completely accurate. It's a good first step, but if you want to be 100% sure, then you might wanna just reach out for your old laptop or try it on the machines that it's gonna be run on. Do you know what those services are? Where should we find you on Twitter for a response? I think it's BrowserStack, that's one that I have used. If you don't wanna sign up for it, you get about a minute I think on each device and different versions, so you can work your way through the different versions and get an idea of the performance. Sounds good.

Alternative Solutions and Testing

Short description:

There were different solutions and debugging paths tried, including the Usync external store. Finding the right balance between synchronous rendering and considering the various user environments is crucial. Testing the full life cycle of the component and accounting for different devices, like iPads, is important.

The next question, let's scroll through. Were there other solutions that were tried other than the ones presented or other debugging paths you went down? Yes, I did try a lot of different things. Yeah, so the Usync external store nearly got us there, but then it also, it relied on us kind of turning off the features within AG Grid, which is using animation frames to control when things are rendered, so there's a combination of factors going on there. But yeah, there were definitely different approaches, all had different pros and cons. And this is something which I'm actually constantly kind of reviewing as well. So we want AG Grid to be the best performance across all the different users that we've got. And you've gotta find that fine balance between, I could have made everything synchronous and just assumed everyone had a dev machine, and then we would have shipped that, and then real user use cases would have come in, saying, why is the grid not working very well? And I think it also would have caught devs out, because most devs have got more powerful machines than where their application is being used. So you've gotta test the full life cycle of where this component is used, and then make compromises about that. I love how you're talking about that. Earlier on, we were talking about how this new generation of developers actually use iPads as opposed to dev machines. And so I love the fact that you're accounting for all of that in your testing.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

React Advanced Conference 2022React Advanced Conference 2022
25 min
A Guide to React Rendering Behavior
Top Content
React is a library for "rendering" UI from components, but many users find themselves confused about how React rendering actually works. What do terms like "rendering", "reconciliation", "Fibers", and "committing" actually mean? When do renders happen? How does Context affect rendering, and how do libraries like Redux cause updates? In this talk, we'll clear up the confusion and provide a solid foundation for understanding when, why, and how React renders. We'll look at: - What "rendering" actually is - How React queues renders and the standard rendering behavior - How keys and component types are used in rendering - Techniques for optimizing render performance - How context usage affects rendering behavior| - How external libraries tie into React rendering
React Summit 2023React Summit 2023
32 min
Speeding Up Your React App With Less JavaScript
Too much JavaScript is getting you down? New frameworks promising no JavaScript look interesting, but you have an existing React application to maintain. What if Qwik React is your answer for faster applications startup and better user experience? Qwik React allows you to easily turn your React application into a collection of islands, which can be SSRed and delayed hydrated, and in some instances, hydration skipped altogether. And all of this in an incremental way without a rewrite.
React Summit 2023React Summit 2023
23 min
React Concurrency, Explained
React 18! Concurrent features! You might’ve already tried the new APIs like useTransition, or you might’ve just heard of them. But do you know how React 18 achieves the performance wins it brings with itself? In this talk, let’s peek under the hood of React 18’s performance features: - How React 18 lowers the time your page stays frozen (aka TBT) - What exactly happens in the main thread when you run useTransition() - What’s the catch with the improvements (there’s no free cake!), and why Vue.js and Preact straight refused to ship anything similar
JSNation 2022JSNation 2022
21 min
The Future of Performance Tooling
Top Content
Our understanding of performance & user-experience has heavily evolved over the years. Web Developer Tooling needs to similarly evolve to make sure it is user-centric, actionable and contextual where modern experiences are concerned. In this talk, Addy will walk you through Chrome and others have been thinking about this problem and what updates they've been making to performance tools to lower the friction for building great experiences on the web.
React Advanced Conference 2022React Advanced Conference 2022
29 min
Understanding React’s Fiber Architecture
Top Content
We've heard a lot about React's Fiber Architecture, but it feels like few of us understand it in depth (or have the time to). In this talk, Tejas will go over his best attempt at understanding Fiber (reviewed by other experts), and present it in an 'explain-like-I'm-five years old' way.

Workshops on related topic

React Summit 2023React Summit 2023
170 min
React Performance Debugging Masterclass
Featured WorkshopFree
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)
React Advanced Conference 2021React Advanced Conference 2021
132 min
Concurrent Rendering Adventures in React 18
Top Content
Featured WorkshopFree
With the release of React 18 we finally get the long awaited concurrent rendering. But how is that going to affect your application? What are the benefits of concurrent rendering in React? What do you need to do to switch to concurrent rendering when you upgrade to React 18? And what if you don’t want or can’t use concurrent rendering yet?

There are some behavior changes you need to be aware of! In this workshop we will cover all of those subjects and more.

Join me with your laptop in this interactive workshop. You will see how easy it is to switch to concurrent rendering in your React application. You will learn all about concurrent rendering, SuspenseList, the startTransition API and more.
React Summit 2020React Summit 2020
125 min
Getting Started with Suspense and Concurrent Rendering in React
Featured Workshop
React keeps on evolving and making hard things easier for the average developer.
One case, where React was not particularly hard but very repetitive, is working with AJAX request. There is always the trinity of loading, success and possible error states that had to be handled each time. But no more as the `<Suspense />` component makes life much easier.
Another case is performance of larger and complex applications. Usually React is fast enough but with a large application rendering components can conflict with user interactions. Concurrent rendering will, mostly automatically, take care of this.
You will learn all about using <Suspense />, showing loading indicators and handling errors. You will see how easy it is to get started with concurrent rendering. You will make suspense even more capable combining it with concurrent rendering, the `useTransition()` hook and the <SuspenseList /> component.
JSNation 2023JSNation 2023
170 min
Building WebApps That Light Up the Internet with QwikCity
Featured WorkshopFree
Building instant-on web applications at scale have been elusive. Real-world sites need tracking, analytics, and complex user interfaces and interactions. We always start with the best intentions but end up with a less-than-ideal site.
QwikCity is a new meta-framework that allows you to build large-scale applications with constant startup-up performance. We will look at how to build a QwikCity application and what makes it unique. The workshop will show you how to set up a QwikCitp project. How routing works with layout. The demo application will fetch data and present it to the user in an editable form. And finally, how one can use authentication. All of the basic parts for any large-scale applications.
Along the way, we will also look at what makes Qwik unique, and how resumability enables constant startup performance no matter the application complexity.
React Day Berlin 2022React Day Berlin 2022
53 min
Next.js 13: Data Fetching Strategies
Top Content
WorkshopFree
- Introduction- Prerequisites for the workshop- Fetching strategies: fundamentals- Fetching strategies – hands-on: fetch API, cache (static VS dynamic), revalidate, suspense (parallel data fetching)- Test your build and serve it on Vercel- Future: Server components VS Client components- Workshop easter egg (unrelated to the topic, calling out accessibility)- Wrapping up
React Advanced Conference 2023React Advanced Conference 2023
148 min
React Performance Debugging
Workshop
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)