Understanding Rendering Patterns

Rate this content
Bookmark

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.

9 min
12 Dec, 2023

Video Summary and Transcription

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.

Available in Español

1. Introduction to Rendering Patterns on the Web

Short description:

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

Short description:

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.

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 Summit 2022React Summit 2022
20 min
Routing in React 18 and Beyond
Top Content
Concurrent React and Server Components are changing the way we think about routing, rendering, and fetching in web applications. Next.js recently shared part of its vision to help developers adopt these new React features and take advantage of the benefits they unlock.In this talk, we’ll explore the past, present and future of routing in front-end applications and discuss how new features in React and Next.js can help us architect more performant and feature-rich applications.
React Advanced Conference 2021React Advanced Conference 2021
6 min
Full-stack & typesafe React (+Native) apps with tRPC.io
Top Content
Why are we devs so obsessed with decoupling things that are coupled nature? tRPC is a library that replaces the need for GraphQL or REST for internal APIs. When using it, you simply write backend functions whose input and output shapes are instantly inferred in your frontend without any code generation; making writing API schemas a thing of the past. It's lightweight, not tied to React, HTTP-cacheable, and can be incrementally adopted. In this talk, I'll give a glimpse of the DX you can get from tRPC and how (and why) to get started.
React Summit 2023React Summit 2023
22 min
Thinking in React Query
Top Content
In this talk, I'll explain React Query from a different perspective. After having maintained React Query for over two years and having answered many questions (often the same ones multiple times), I feel like there might be a fundamental understanding missing about the lib. I'll start with a quick introduction about my journey into open source and how I got to know React Query, followed by showing which mindset change is beneficial when working with React Query - how to "think in React Query". I'll have 3 major takeaways: 1) React Query is not a data fetching library It's an async state manager, we'll quickly talk about what makes a state manager, why React Query is one and what "async state" means. 2) staleTime is your best friend I've seen a bit of confusion about how to use React Query as a state manager, so I'll explain why setting staleTime is mostly all you need 3) parameters are dependencies This is important to understand to show the boundaries between client state and server state, and is essential when doing state management with React Query I will then end with a note on "separation of concerns" and about the tradeoffs of just calling `useQuery` wherever you need it in your component tree.
React Advanced Conference 2021React Advanced Conference 2021
20 min
Advanced Patterns for API Management in Large-Scale React Applications
Top Content
In this talk, you will discover how to manage async operations and request cancellation implementing a maintainable and scalable API layer and enhancing it with de-coupled cancellation logic. You will also learn how to handle different API states in a clean and flexible manner.
React Summit 2023React Summit 2023
19 min
7 TypeScript Patterns You Should Be Using
Top Content
In this talk, we will be going over a number of common useful and best-practice-proven TypeScript patterns to use in React 18. This includes how to correctly type component properties, children and return types, using React's built-in types, typing contexts, and the usual enum rant (but constructively).

Workshops on related topic

React Advanced Conference 2022React Advanced Conference 2022
206 min
Best Practices and Patterns for Managing API Requests and States
Workshop
With the rise of frameworks, such as React, Vue or Angular, the way websites are built changed over the years. Modern applications can be very dynamic and perform multiple API requests to populate a website with fresh content or submit new data to a server. However, this paradigm shift introduced new problems developers need to deal with. When an API request is pending, succeeds, or fails, a user should be presented with meaningful feedback. Other problems can comprise API data caching or syncing the client state with the server. All of these problems require solutions that need to be coded, but these can quickly get out of hand and result in a codebase that is hard to extend and maintain. In this workshop, we will cover how to handle API requests, API states and request cancellation by implementing an API Layer and combining it with React-Query.
Prerequisites: To make the most out of this workshop, you should be familiar with React and Hooks, such as useState, useEffect, etc. If you would like to code along, make sure you have Git, a code editor, Node, and npm installed on your machine.