React has exploded in popularity thanks to the performance and unrivaled developer experience the virtual DOM and reconciliation could offer. But as our apps grew, we started pushing the boundaries of managing client state in a performant way. Let's see how to achieve fine-grained reactivity and what resumability brings to the table.
Understanding Rendering Patterns
AI Generated Video Summary
This Talk discusses rendering patterns on the web, including the use of React and the concept of memoization. It explores the idea of using signals to change data without a full re-render and how frameworks like SolidJS, Vue, Svelte, and Angular are adopting signals. The React team is developing React for Get, a compiler that provides auto-memoization to reduce unnecessary re-renders. Different frameworks have their own ways of using signals, such as shallow ref or ref in Vue, use signal in Quick, and defining and accessing signals in Angular and Svelte.
1. Introduction to Rendering Patterns on the Web
Hello, React Neighborland. Today, I will discuss rendering patterns on the web, including the use of React and the concept of memoization. React introduced the idea of abstracting the DOM and using a virtual DOM to batch changes and improve performance. However, when using a context provider, all child components are re-rendered, leading to potential performance issues. To address this, the React team is developing React for Get, a compiler that provides auto-memoization. This allows components to be memoized based on the props they use, reducing unnecessary re-renders and improving performance. Memoization, however, is not fine-grained reactivity, leading to the exploration of alternative ideas to challenge the virtual DOM.
Hello, React Neighborland. We're here to talk about rendering patterns on the web. So first of all, who am I? My name is Atila Fasina, and I'm a DevRel engineer at Crab Nebula. I'm also a Google Developer Expert and you can find me on each one of those networks over there. I have a handy ... I got a handy ... some handy shortcuts for you, because naming things on the web are hard, and you can also find me right here on this platform at atila.io.
So let's talk about rendering things on the web. First there was React with a bunch of very cool ideas, like using the UI as a function of the state, and with that came declarative UI, rendering props, Unidirection flow, and But ensuring consistency can make the DOM slow, because removing and re-appending elements to the DOM is a very expensive action. So React and other frameworks had the idea of abstracting the DOM, and then we can batch all the changes, and then re-concile the changes and add everything together in one go. So with that, we have this rendering model, where you can put together all the changes in a batch, and we abstract the DOM away in a virtual DOM, and that gives us this tree of components based on the data that they have. So essentially in this case, you have the parent component with props A and B, but then if prop A changes, everything that depends on A is also going to change. But we don't stop over there, because there's no way of tracking in the virtual DOM what are the things that change. So everything that actually is a child of where the prop A lives and is defined gets re-rendered as well. And if you're a React developer, which I think most of you are, you've seen that a bunch of times, you've talked about that bunch of times, and nothing like that is new. In my experience, what gets new is when we have a context provider in this case. And then we are inclined to think that if we change a prop in a context provider, only the components that use that prop are going to re-render. But essentially what happens is that everything that's a child of that component provider changes. And that's why, in my experience, I've seen a bunch of people stepping on the landmine because you end up re-rendering your entire app with a single prop change. So with that in mind, the React team is working on this compiler, which is React for Get, which is besides ensuring a bunch of nice best practices, it's also going to provide auto-memorization. What is that? What that means is that components are going to be memoized based on the props that they use. So if a component uses prop A, it's going to be memoized in order to only render if prop A changes. And then if it's not using any prop, only local states, not going to be rendered based on other changes, and for props B and so on. So that can encapsulate the re-renders and contain them. That's a very nice idea and by doing that, it can afford some renderings to not actually happen, and therefore, the mental model becomes a little bit easier to reason about when you're talking, especially to people coming into React. But essentially the idea of memoization is for big computations. So the auto-memoization part is more, in my opinion, a DX thing than an actual change to a performance optimization. To that we also need to say that memoization is actually not fine-grained reactivity. And with that, we open the way of going a little bit more granular. So some ideas came up to challenge the VDOM.
2. Signals and Their Usage in Frameworks
Instead of re-rendering the whole component, signals allow you to change the data without needing a full re-render. Frameworks like SolidJS, Vue, Svelte, and Angular are evaluating or adopting signals. Fine-grain reactivity requires more control and awareness of data updates. Understanding the chosen tool is essential. Different frameworks have their own ways of using signals, such as shallow ref or ref in Vue, use signal in Quick, and defining and accessing signals in Angular and Svelte. Developers are exploring better ways to describe UI with signals. Come chat with me on X or find me on YouTube.
For example, instead of rendering and batching the changes and re-rendering, a new idea came on if you render things, you can touch only what you changed. So then that essentially goes into decoupling the rendering logic from the data. And that's exactly what signals are about. You can change the data without needing to re-render your whole component. It uses the observer pattern, which essentially, the data is capable of notifying you when changes happen. Your rendering system can track if the changes happen. And then, whenever you're rendering, the part that's responsible for your UI can then get the new value in this case.
So looking into our landscape of frameworks, what then happened is SolidJS came and said, Oh, I like Signals, let's bring them back. And all the other frameworks were more towards VDOM, some of them like Svelte and Vue, more specifically, were doing some other stuff that were more in line with what Signals are. And fast forward a couple of years, all the frameworks are actually evaluating or adopting Signals as we speak, so this graph is actually very representative of like Vue 3 and Svelte 5, but QUIC and Angular already have Signals somewhere in their code base.
But then I would be disingenuous by not talking about the trade-offs, one of them is that fine-grain reactivity is a little bit less resilient than the VDOM because it requires you to have more control and it requires some care on not tossing out everything and then doing it. So if you're going to go fine-grain, you need to be more aware of how your data is updating and making sure that your component can respond. Also frameworks like SolidJS has a bunch of helpers that can help you ensure this reactivity in order to provide a great developer experience. But anyway the takeaway of my talk is that there's actually no free lunch. You may choose VDOM, you may choose Signals, but in the end of the day you need to understand the tool you're using.
And just so you can wrap up, let's have a look about how Signals are used on different frameworks. Like for example Vue, you have the shallow ref or ref where you can define them. In Quick you have the use signal and then you can set up, you can change the value like that and you can access the value with the countout value and essentially the compiler is going to turn them into getters and setters like signals need to. For Angular you define a signal like this and you can either set it or update the signal based on the previous value and you can access the signal by a function getter. For Svelte you define a signal and you can create a getter and you can create a setter for that signal as well.
So to recap our short talk, what happened is that we had a model that was pretty good for what we had before with React and the virtual dom and all the other frameworks using them. Right now a lot of developers are actually thinking there are better ways to describe the UI with signals and stuff and so more frameworks are going towards that direction and I do recommend you to have a look at that. And that was all I had for you. So thank you very much. Please come around and let's chat on X or see me on YouTube.