Fine-Grained Reactivity Without Any Compiler

This ad is not shown to multipass and full ticket holders
React Summit US
React Summit US 2025
November 18 - 21, 2025
New York, US & Online
The biggest React conference in the US
Learn More
In partnership with Focus Reactive
Upcoming event
React Summit US 2025
React Summit US 2025
November 18 - 21, 2025. New York, US & Online
Learn more
Bookmark
Rate this content

Achieving high-performance reactivity in React without compromising the developer experience has always been a key challenge. When building real-time applications designed to display hundreds of millions of rows without noticeable lag, fine-grained reactivity is essential. But when I started my journey at Pigment, neither Recoil, Jotai, nor Zustand were mature enough, and React Compiler was not yet a thing. Let's explore together how we managed to ingest, display, and update huge datasets seamlessly without sacrificing the developer or the user experience.

This talk has been presented at React Day Berlin 2024, check out the latest edition of this React Conference.

FAQ

Fine-grained reactivity refers to a system where updates are highly targeted and specific, occurring at a deeper level than just component level. In such systems, updates happen directly at the level of individual elements, like spans holding values, instead of re-rendering entire components.

Yes, React is considered reactive. When state changes occur, React components update to reflect those changes. However, React's reactivity is not as fine-grained, which means it might re-render more components than necessary for a small change.

Pigment faced challenges with React's reactivity when dealing with large grids of data and real-time updates. The company found that React re-rendered more components than necessary, which could lead to performance issues.

Pigment implemented a custom reactivity system on top of React. This involved creating hooks like useShell, useComputed, and useWatch, which allowed for more fine-grained updates and reduced unnecessary re-renders.

The useShell hook in Pigment's solution creates a 'shell' that holds a value and a setter function. This shell enables updates to happen without triggering React to re-render the entire component, allowing for more efficient state management.

Pigment chose to build a custom solution because existing libraries at the time did not fully meet their needs for fine-grained reactivity. Additionally, they wanted a system that would be easy for their developers to use and integrate with React.

The useWatch hook connects a shell to React, notifying React of changes in the shell's value. It uses React's useSyncExternalStore function to subscribe to updates and provide the current value to React, ensuring components update when necessary.

Pigment's custom reactivity system allows for more efficient updates, reducing the number of unnecessary component re-renders. This improves performance, especially when dealing with large datasets and real-time data updates.

Yes, Pigment considered moving away from React and using native JavaScript for certain components due to performance issues. However, they chose to stay with React to maintain a consistent development environment and leverage React's capabilities.

The main reason for optimizing their reactivity was to ensure that their application could handle large datasets and real-time updates efficiently, providing a smooth user experience without unnecessary lag or performance issues.

Nicolas Dubien
Nicolas Dubien
29 min
13 Dec, 2024

Comments

Sign in or register to post your comment.
Video Summary and Transcription
My name is Nicolas, and today, I'm going to talk about Fine-Grain Reactivity without the compiler this time. React is reactive, but it re-renders unnecessary components. Fine-grained reactivity is achieved by updating specific elements instead of whole components. Pigment encountered reactivity problems while building real-time financial data boards. They created their own reactive system on top of React to achieve fine-grained reactivity. They used custom hooks like useShell, useComputed, and useWatch to integrate React with their reactive system. They also considered using native JavaScript for optimization but chose to preserve React. They use external libraries like Zestand for flexibility, and maintaining reactivity during React updates has not been a problem.

1. Introduction to Fine-Grain Reactivity

Short description:

My name is Nicolas, and today, I'm going to talk about Fine-Grain Reactivity without the compiler this time. We first need to understand what is Reactivity about and is React reactive today? Let's see if React is reactive by considering a simple application made of three counters. To make it work properly, you need to move the states higher in the tree and pass props down to the counters and total. The app component is the main component in this application, made of three states passed to each counter. This is a basic app.

My name is Nicolas, and today, I'm going to talk about Fine-Grain Reactivity without the compiler this time. This is the last talk before the launch. After that, you will be able to lunch, so please stay.

But before we go into Fine-Grain Reactivity, we first need to understand what is Reactivity about and is React reactive today? In order to understand what is Reactivity about, I took this definition from the Vue ecosystem. When you modify the state, the Vue update, it makes state management simple and intuitive. We have another version of this one, which is just saying that the DOM or the Vue is a function of the state.

So the first question we should ask ourselves is, is React reactive or not? And in order to answer that question, a very simple thing to do is just to give it a try and to see if React is reactive. So in order to do that, I will consider this very simple application. It's made of three counters. So the first three lines are just counters. You can increment, decrement the counters, and you can see the value of the counter. At the end, you have the last line, and the last line is just the total of the three counters above.

If you were to build such application, you may come up with something like that, with three main components, one app component, one counter component, and a total. And obviously, within your app, you will use the counter component three times. But with that one, it doesn't work that well. You need to put some, I would say, interactivity for the users to be able to use your counters. So you will put some states directly within the counters, and with that, you are just able to play with each of the counters independently. You can increment, decrement your counters, and it will be fine for the users. But at some point, you need the total, and if you need the total, you need to know about the state of each of these counters directly within your total. And at this point, the usual trick is to move the states higher in the tree, and so we get the first three states directly in the app, and you just move the props down to the counters and to the total.

Now that we have everything, let's see how it works at the end. So let's see what is the code of this app component, because it is the main component in this whole application. So we'll just, this is like how your app component will be in that case. So my app component is made of three states. Each one has a value and a set value. And you can see that I pass the value plus the setter function directly to each of the counters. And at the end, you can see the total component, which is receiving the three values. This is a basic app.

On the right of the screen, you can see the app in action. So I'm just playing with this application.

2. Reactivity and the React Compiler

Short description:

I'm incrementing, decrementing counters, and you can see that everything works well. React is reactive, as the values in my state are correctly replicated on the screen. However, when I enable the React DevTools, I see that every time I increment or decrement a counter, not only that counter and the total are rendered, but also all the other counters and the app component. Recently, I tried using the compiler and noticed a slight difference. The counter and the total are rendered, but the app component is also rendered. I wanted to understand what the compiler was doing, so I checked the playground with the code.

I'm incrementing, decrementing counters, and you can see that everything works well. So React is reactive, because at the end, when I click on something, I can see that the values that I've installed in my state are just correctly replicated within the screen. I can see the total being updated, I can see the values being updated. But there is something I enable in the React DevTools that is just highlighting everything in the screen. Whenever I click somewhere, something is highlighted. Everything which is highlighted is around a rendering thing. So whenever React is rendering one of my components, you can see this small arrow stop around the component. It means that my function has been called again. And in my case, you can see that whenever I increment or decrement a counter, not only this counter plus the total has to be rendered again, but also all the other counters plus the app itself.

The first time I saw that, I was like, what is doing React? It's crazy. I mean, like, what the hell? I mean, I'm incrementing one counter, and everything got recomputed again and again. And I had to take it. I mean, it was OK. I went, maybe it's normal. Let's say it's normal. And recently, I've fallen under compiler stuff. I was like, yes. I will be saved. Maybe I will be saved this time. I enabled the compiler, again, the code I showed you. This time, we get something a bit different. When I increment the counter, we just see a render of this counter plus the total, obviously. But we also see a render of the app component. So it gets better. It's better, or at least, we'll say it's more intuitive. But as the compiler is doing a very strange thing, I wanted to get a look into what it was doing.

So I checked the playground with that piece of code. So if we toggle the playground of React compiler against that piece of code, we get the following more precisely, this code. I will not spend too much time in it. But there is a question.

3. Fine-Grained Reactivity and Journey at Pigment

Short description:

Is the React compiler doing fine-grained reactivity? In a fine-grained reactive system, updates are not at the component level but deeper in the tree, directly affecting specific elements. The React compiler, as seen before, is not fine-grained reactive because it still re-renders the app unnecessarily. Let's talk about fine-grained reactivity and my background as a lead software engineer at Pigment, where we encountered reactivity problems and found solutions. Follow me on social networks and check out my open-source library, TestCheck. Now, let's explore how to make our application more reactive by discussing our journey at Pigment and examining an example of countries not being updated correctly.

Is it the right tool to use in order to get this reactivity in place? I will not answer that question, honestly. But it's important to take in mind that maybe it can be the right tool. Maybe it's not the right tool. But the main question we should ask ourselves, because the talk is about fine-grained reactivity, is, is the compiler doing fine-grained reactivity at the end? And in order to understand if it is doing or not fine-grained reactivity, we need to understand what is fine-grained reactivity about. So I will take the definition of solid JS. And the definition is the following. In a fine-grained reactive system, an application will not have the ability to make highly targeted and specific updates. What is important there is that the updates are not at component level. They are deeper in the tree. They are directly in the span holding the value of the counter. In the case of this presentation, I will not dig that much in this fine-grained reactivity stuff. I will stop at component level. But even at component level, if we were fine-grained reactive, we would have expected to re-render the counter and the total, but not the app. So what we've seen just before with the React compiler is not even fine-grained reactive at all, because we missed, we still re-rendered the app for nothing. So let's talk a bit about fine-grained reactivity. But before we go there, I will just tell you a little bit who I am and why I'm talking about fine-grained reactivity today. My name is Nicolas Dubin. I'm working as a lead software engineer for Pigment. Pigment is not Pigment CSS, because lots of people are asking me about that, so I prefer like telling it. And at Pigment, we are displaying big grids of data with millions of cells and charts all the places. And we add some problems with reactivity of React, and we add to come up with solutions in order to make the application reactive enough for clients to be happy with it. You may follow me on some social networks. I have some there. And as Nathaniel said, I'm the author of the open-source library, TestCheck. So maybe you know it or not. And you can find more about Pigment at engineeringpigment.com. But let's move on to the main topic of this talk, how to make our application a bit more reactive. And I will dig you through our journey at Pigment. So at Pigment, when we fall on this very simple example about like countries not being updated the right way, we wanted to understand what was happening, and if we can make them better. And the first thing we did was just taking back this example and trying to understand what was going wrong with this one.

4. Re-rendering and Performance Optimization

Short description:

We analyzed an example where changing the state of one component in React triggers a re-render of the entire app component and its children. This is due to React's rules. The use of context in React can also lead to re-renders. To improve performance, we applied memoization to the counter component. We started our journey at Pigment with the goal of improving our code and making it more efficient.

We took this example, and we considered the idea of, we will increment one of these countries and try to understand what's going on. So we decided to say that the third country in this example, which is green, all the green value will move to the red value. So let's do it. And the first thing that happened there is that React will re-render the app component. And the reason of that is that in React, whenever you change the state of one component, this component has to be re-rendered. This is one of the rules of React. And this is working that way because it has been designed that way. So you have to re-render the app component, no matter why you have to re-render that, because it's holding your state.

The next thing is about all other components. The second rule in React is that whenever a component gets re-rendered, all the children of this component will be re-rendered, too. So we got to re-render counter, counter, counter, and total. And this is the main reason why everything got re-rendered the first time. We need to re-render app because it's holding the state. We need to re-render all the countries because all the countries are children of the app component. And the app component got re-rendered. And there is a last one. I just want to give it because it's pretty important. Most of the time, people complain about context being slow. And one of the reasons of context being slow is because whenever you use context in React, you can consider that the value of your context is some kind of state of the component consuming the context. So it means that whenever you use a context, you will be subject to re-renders, as if the state changed directly within your component using the context. We are not using context in this case, so we are good with this one. But let's try to make it better. Let's do it incrementally. When we started Pigment five years ago, we started with this piece of code, let's say. And the idea was to make it better. So how can we make it better? First idea is that we can fall into an internet about memorizing stuff. So we just put memo stuff around the counter. So this is what I did there. And now that I have the memo stuff and my application, I can just redo the check with it together before. I have still this application, but I made a typo in the slide initially because we have several props for the countries.

5. Stability of Props and useCallback

Short description:

We have two props for each country: value and incremental function. When updating the third counter, we need to re-render the app component. React will compute the new properties for each counter, but the increment function is not stable. We can use useCallback to make it stable.

You can see we have two props for each country, one which is the value and one which is the incremental function. We will perform exactly the same update as before, we will play with the third counter. So we move the third counter from green to red, same as before, we need to re-render the app component. We have no choice. This is the first rule of React. So we have to do that.

Then React will render the component and will compute the new properties of each counter. But the problem is that for each counter, we receive two properties. One of them will be stable, the value. For the counter one, for instance, the value is still blue. It used to be blue before. But it also receives another stuff, which is another property, which is the increment function. And this one is not stable anymore. The reason of that is when you see this code, whatever we call the app function, we recreate a new increment function. Because increment is just a lambda function. So it's not stable at all. Whatever we call app, we create a new one. So there is a trick to make it stable, which is just to use useCallback.

6. Reactivity at Pigment

Short description:

We wanted to be more reactive and fine-grained reactive at Pigment while building boards to display real-time financial data. The data needs to be updated frequently to ensure that all users can see it in real time.

With that piece of code, we just reach what React compiler was mostly doing. But we are, as I said, not fine-grained reactive. We still have things that are re-rendering that should not re-render. So I will tell you about Pigment, about what we did at Pigment. Because it was not enough for us to play with memo every time, and it was a bit adding extra complexities to the code base. So we wanted to do something a bit different.

To make it simpler for developers to do it, but also to be more reactive, more fine-grained reactive. So at Pigment, we are building boards to display financial data of clients. This financial data can be displayed as graph, as grids. And it can contain multiple kinds of data, including formatting, figures, and text. All the data is real time. People want to input data, and they want all their colleagues at the opposite of the world to see the data in their real time. It means that we have to update the data in several times per minute, several times per hour, depending on the usage of the platform.

7. Fine-Grained Reactivity for Real-Time Data

Short description:

The data there is very simple. We have big clients with millions of cells. We use context for labels, but it can have performance issues. We built our own reactive system on top of React to achieve fine-grained reactivity for real-time data.

The data there is very simple. It's just made of a few figures. What's about my chicken? Because I used to have chicken in the past, and you can see the number of eggs of each of them. It's private data, so please don't take pictures of it. No, you can take it.

And so this one is pretty small, but you can imagine that we have big clients with millions of cells, which are not even fitting in Excel in general. So we don't just render small grids like this one. Otherwise, it would have been simple.

And we have also labels. The labels have been used everywhere. So we have labels that are in sync with all the charts, all the graphs. So we need to put them at some place, which is shared between all of them. And today, we use context. And as I said, context has some troubles with performance if they are not used the right way. And so we have real time data all the places with components sharing this data between one of each others.

This is just the grid at Pigment. And there you can see it in action. So we have a user which is playing with the grid. Someone is changing the data. And you can see wherever there is a rerender of components. And you can see that only the cells that have been touched, only the errors that have been touched will be rerendered in the screen. In order to achieve that, we had to build our own reactive system on top of React. And this is how it works. So we took this very simple grid. This one is a pivoted grid. So if you played with Excel in the past and if you made pivoted data stuff, a pivoted grid is started from a CSV flat file. So you have a flat set of lines. And you have a configuration that is telling you what are the columns, what are the rows in your grid to be displayed. In that case, my columns are the kind of chicken, so Sussex and Azure, and the name of the chicken. They both have names.

8. Details of Data Configuration and Algorithm

Short description:

In the grid, errors can span multiple columns and rows. Each cell has a specific location. The algorithm uses data in a CSV format with specified columns. The lines can be out of order. Configuration includes kind, chicken, and year.

One of them is called Bianca, the other one Bernard, and one is Jasmine. So it's just my configuration. In columns, I have the kind, then the name. And in rows, I just have the years. Something very important to notice in this display is that some errors are spanning over multiple columns. It can be over multiple rows, too. And there is also something interesting.

In pivoted grids, you have some location for each cell. So for instance, the 166 value is for Sussex, Bianca, and 2020. It can be interesting to know it in the algorithm because we need it at some point in order to get the right data. In terms of data that we receive in the algorithm, it's mostly lines. So it's just flat with all the details. So you can see it as a CSV with all columns being specified. Sussex, Bianca, 2020, 166. These lines can be out of order. And then we have the configuration part. Kind, chicken, and year.

9. Algorithm Overview and React Compiler Limitations

Short description:

I will quickly show you the algorithm. We take the line plus the configuration, compute the errors of the display, and render the rows, columns, and cells. We have a component with extra controls. When we re-render elements, including the grid component, the React compiler doesn't work well. We need to find another solution.

I will just show you quickly the algorithm. I will not dig into too much detail about this algorithm. You have a copy of it directly on my GitHub.

What is important is that we really take the line plus the configuration, meaning that we take the CSV plus the configuration. Then we need to compute what will be the errors of this display, how long they span, if they span on multiple columns or multiple rows, and what are the paths of each column. And at the end, know that we have everything. We can just render the rows, the columns, and the cells. For rows and columns, they are basically the errors.

Know that we have a component ready. We can put it in action so we can put some extra controls on top of it so that we can play with it and see if it's reactive or not. I mean, fine-grained reactive or not. And so this is the display. I have two buttons. One of them is refresh data. It's just syncing back the data from the backend. And the data is the same. And one of them is update one cell. It's updating the first cell in the top-left corner.

In both of these cases, you can see that all the elements have been re-rendered. So we don't, I mean, we re-render all the cells, we re-render all the errors, we even re-render the grid component itself. But hopefully, today, we have the React compiler, so we are probably safe and we can stop this talk at this point. But when we started Pigment, it was not the case. But let's give it a try. And it doesn't work that well. So we'll move away from it for now. But yeah, React compiler is not doing that much for this case. It's probably too complex for it to be able to do something. Maybe we have to change the way we code our component to make it work. But at the moment, with that piece of code, it doesn't succeed. So anyway, we had to come up with something else.

10. Creating a Custom Value with useShell

Short description:

Five years ago, there were no React compiler or system to help us. The useState hook is the main cause of our troubles. We want to preserve useState, so we create our own value with useShell. It's similar to useState but doesn't trigger re-renders. React ignores the changes made with useShell.

Because five years ago, there were no React compiler, no system, no stuff like that to help us in that area. But there is one thing we like in React. This is this useState. And this is the main reason of all our troubles. Because when we use useState, whenever the state is changing, we have to re-render the component. So up. So this is not great. But we want to preserve useState. It's cool. I mean, people are used to use this kind of abstraction. They want something that looks as useState.

So what if we create our own value? What if we say we have a useShell, which is creating a shell? So let's see what it means. useState is taking a value and it's returning this value plus a setter. So this time it's blue. When we call the setter function, we update the value. We moved it to green. useShell will be a bit similar in some way. So it's taking a value as useState. But it's returning a shell holding this value plus a setter function. Whenever you set the function, you don't change the shell. But you change the value, which is within the shell. From a React point of view, React doesn't see anything. It considers that the state is the same. So we don't re-render anything.

So at this point, we are just saying, React, please ignore my stuff. It works behind the scenes. So this is just a possible implementation for it. You can change it as you want. Internally all shells are made of behavior subjects. If you played with EricGs in the past, you may know behavior subjects.

11. Integrating React and Updating Shells

Short description:

You don't need to know about behavior subjects. We build a state with a behavior subject to create our shell. But we need something different because we can't work with just the value. So we create useComputed, which transforms shells into new shells. We subscribe to the original shell and forward updates to the map shell. With this, we have shells everywhere, but we need to integrate React to see the updates.

But anyway, you don't need to know about behavior subjects to understand the rest of the talk. The idea of a behavior subject is that it's something you can subscribe to to get updates. And you get a sync value. You have a value when you create the components. In order to create our shell, we build a state. The state is just a behavior subject. And in order to update the content of the shell, we create a setter function, which is just putting the new value directly in the behavior subject. Nothing more.

Now that we have our shell, we do have a problem. Because the lines are not anymore lines. We have shells over lines. So we need something different. Because it will not work. We can do something, but if we don't have the value, we can't do anything from the value. So we need to change this code. At this point, what we want to do is create a new shell. Because we don't need the value actually. We just derive the value into something new. So we created another helper, which is called useComputed. useComputed is taking the shells, or multiple shells, and taking it and transforming it into another shell. Usually the signature is the following. So we take a transformation function. This one is transforming blue into green, a shell, which has a blue value, and it returns a new shell, which is holding the transformed value. In terms of implementation, useComputed is creating a shell. So we just create a shell, using useShell, the first helper that we came up with. Then we have to register to the original shell, in order to know whenever there is an update to the original shell, and forward this update directly within the map shell. So what we do is just, we take the shell, we subscribe to this shell, and whenever there is an update, we put that value directly within the map shell, just doing like setter function on the map shell. With all of that, we are now able to have shells all the places. But at some point, we just cut React, because React is unaware of the update. So we need to plug in React at some point, because we need to see the update directly visible in React.

12. Reactivity and useWatch

Short description:

We need to put reactivity back by creating a shell using the useWatch helper. useWatch connects the shell to React and tells it to re-render the code. It unpacks the shell and gives the value to React, transforming the blue value into green. It uses the useSyncExternalStore function of React to subscribe to the shell updates and provide the value to React synchronously.

Otherwise, we just lose reactivity totally, because we don't have reactivity anymore at this point. So we need to put reactivity back, and in order to do that, I can create a shell once again. But I need some new helper, which is useWatch, which will be responsible to connect the shell to React, and tell React, OK, this time I need you. I have a value for you, and you need to re-render this piece of code. And this is what useWatch is doing. useWatch is just taking a shell, unpacking the shell, and giving you the value for React. And it will tell React, OK, this blue is not anymore blue. It's green now. And this is what it's doing. How it works behind the scenes. So we are taking a shell. We use a function of React, which is called useSyncExternalStore. We can receive it as two functions, subscribe and get snapshots. So we have to subscribe to the shell in order to know when there is an update to this shell. And we have to tell React what is this value about, in a synchronous manner with getSnapshots. This is basically useWatch in a simplified way.

13. Plugging Everything Together

Short description:

After plugging everything together, we see that no re-rendering is needed. When updating one shell, the desired render value is achieved. Optimization should always be useful and measured for future usefulness. Visit the company website or check out the repository FASTCHECK.

Now that we have everything together, we can just plug it into our application and see what happens. So this is the same application as before, the same buttons, and this time I'm pressing refresh data, and you can see that nothing has to be re-rendered. Everything has been skipped. We don't re-render anything. And when I click on update one shell, I just see a render value on top of the shell that has been updated. This is what we wanted to achieve.

And before I stop with this talk, I just wanted to tell you something because we went through that path after, I would say, several months iterating over optimization around our application. We had to do it, not because we were happy to do yet another reactivity system on top of React, but because it was needed and we measured that it was a problem to have reactivity stuff not being that reactive. So one thing I will say is, whenever you do optimization, it's not only this kind of optimization, but also be aware to do something that is useful and always measure that it's useful and will be useful in the future. And I think that's all for me today.

You can still visit the website of my company if you want. And otherwise, you have the name of my repository, FASTCHECK. And that's all for me.

QnA

Optimizing with Native JavaScript or React

Short description:

Bianca, the egg-laying queen, had a drastic decline in egg production. We considered using native JavaScript for optimization but decided to preserve React for simplicity and ease of onboarding. Many factors need to be considered before making a decision.

Before we do that, I want to talk about Bianca. Bianca is the chicken, the egg laying queen. She was killing it. She had so many eggs. What happened in the last year? She just dropped off a cliff. Yeah, it was horrible. I would say she died at some point.

OK, wait, hold on. Just a quick question. When you say died, that might have a dark undertone. Did you have chicken dinner at some point in 20... OK, OK, just checking. Just checking. All right. Let's actually focus on important questions here that have been upvoted by everyone.

So the first question is, and one thing we could see as you were going through the solutions, there was more and more complexity happening. Michael, I think Michael, I'm pronouncing your name right, hopefully. Have you considered using just native JavaScript for this solution instead of optimizing the reactivity?

Yeah, initially there was a question about like... I'm not sure I will answer totally to the question, but there was the question of leaving totally React and going native for this component, this precise component. So we wanted at some point to say, OK, the grid is too laggy and users will complain all the time. One of the points that people may add at this point was React will never be able to solve this kind of problem. It was not... It will not have been able to support this kind of stuff. So many people push to just leave React totally and just build, I would say, like native JavaScript, HTML stuff on the side, which will do the same but in a reactive way. And at this point, I feel like I wanted to preserve React because I feel it's better, it will be simpler for people to ramp up in the company, to have like classical solution, even if it's behind the hooks, basically what they use is just native. I mean, it's just hooks at the end. So they just have to know a bit about the abstraction, it's just a matter of three hooks and they can build a UI.

Nice, thank you very much. I feel like there is a lot of factors that go into that decision. And probably for you, you may have to look at the different things in your organization before you make a decision.

Using Zestand and Maintaining Reactivity

Short description:

Zestand was not major enough to try, but we always extract the code in a specific piece of our codebase for flexibility. The implementation behind the scenes is a detail for Pigment's end users. Maintaining the extra reactivity has not been a problem during React updates. It's a trade-off between doing it ourselves or using external libraries. React Compiler launch did not make this work obsolete.

A classic, it depends answer. I love it.

Okay, the next one's come anonymously. I'm not sure I totally understand the question but I'm going to pose it to you and maybe you can... What's the difference versus just using Zestand? I would say, like, in the past, Zestand was not major enough. So when we started, like, five years ago, Recode was there, it just started to be there, and Zestand was just showing itself. It was not really an option at this point. It was not major enough to give it a try, so we never tried. The thing is, we always tried to extract this code in a specific piece of our codebase, so that if one day we want to replace the way the use watch is working behind the scene, we can still say, okay, this is Zestand and there's the scene. Today it's not Zestand, it's the one I showed you. But maybe one day we'll be able, like, to say, okay, we want to use Redux, we want to use MobX, we want to use Zestand, Jotar, whatever the solution behind the scene. Just an implementation detail. I mean, from the end users of Pigment, like the developers that are using these hooks, it's just a matter of using the use shell, using the use watch, and using the use computed. Whatever the implementation under the scene is a detail. So maybe one day it will be Zestand. Maybe not. That's nice. No, for sure. And I like the fact that you've not only just thinking about the solution, but thinking about how the experience of your team as they use this solution is really good.

And we've got a question from Andre, which is that it looks great and it seems quite complex. Do you think it pays off the complexity, considering you're going to have to maintain this extra reactivity you've built in the future, especially as React continues to change? Yeah, it has been a question for a long time. When we started we were at React 16, and until now, we stopped at 18 for now. But we never had problems migrating this one. I mean, the whole stuff around these three hooks is highly tested, and even the tests were passing from one release to another. It's not the part that broke when we bumped to other releases of React. It's pretty limited and the size of the code is pretty limited to be safe. Always this kind of trade-off between doing it on your side or taking an external library to do it for you. But we did that in the past because other solutions were either not aligned with what we were looking for, or maybe we just missed the solution in the past. And this is part of both of the problems, I think, at the same time. When React Compiler was launched, were you worried for a second, or that this work was obsolete instantly? No, I don't think so.

Remaining Questions and Closing Remarks

Short description:

We'll still need it in various places, but not for this specific case. The chicken came first. Nicolas's favorite question is about going native and realizing the problem is not the library, but how we use it.

I think we'll still have to need this one. I mean, it's not solving all the problems. I think it will help, honestly. I think we'll need it. We'll need to plug it because it will help a lot in various places. But for this specific place, it will not.

And the last question, I saved it till last. Which came first, the chicken or the egg? It was the chicken, in my case. I don't know for others, but it was the chicken. The chicken. In his case, it was the chicken.

Nicolas, before we go and before they give you a round of applause, which was your favorite question so far? I pretty like the one about going native because I think it's one of the questions that people may ask themselves. I mean, whenever you use a library, you often think that the problem is the library and the way you use the library. It was the question that we stumbled upon in pigment for quite a few months until we said, okay, the problem is not the library. The library is able to do things which are quick. The problem is how we did it. Awesome. All right. So, Michael, make sure you come and find Nicolas and claim your mug. Can we all give Nicolas a round of applause one more time? What an amazing talk. Thank you. Thank you.

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

SolidJS: Reactivity Unchained
JSNation 2022JSNation 2022
20 min
SolidJS: Reactivity Unchained
Solid.js is a declarative JavaScript library for building user interfaces that addresses performance optimization. It introduces fine-grained reactivity and avoids using a virtual DOM. The Talk explores rethinking performance and reactivity in web applications, understanding reactivity and primitives, and creating DOM elements and using JSX in Solid.js. It also covers rendering components, sharing state, and the advantages of fine-grained rendering and the reactive approach in Solid.js.
5 Years of Building React Table
React Summit 2022React Summit 2022
24 min
5 Years of Building React Table
Top Content
React Table is a popular table library that started with HTML5 tables and transitioned to React. It faced challenges with integration and user requests, leading to the development of React Table. The introduction of the Headless UI pattern and TypeScript support improved the library's capabilities and quality. Generics and TypeScript played a significant role in reducing the code size and improving development. React Table is now going framework agnostic and partnering with AG Grid.
Modern State Management with Vue 3
Vue.js London Live 2021Vue.js London Live 2021
22 min
Modern State Management with Vue 3
Top Content
Vanessa introduces Vue Free and discusses the benefits of using the Composition API. The order of execution and grouping logical units using the Composition API is explained. The Composition API is used for state management and refactoring components. The speaker shares their initial experience with state management using Vuex. Composables are explored as an alternative for state management in Vue 3.
Taking Vue.js to the Backend
Vue.js London Live 2021Vue.js London Live 2021
23 min
Taking Vue.js to the Backend
This talk explores using Vue.js in the backend, specifically focusing on Vue 3 Reactivity. It discusses how Vue 3 Reactivity leverages ES6 proxies to update changes and intercept hooks. The talk also covers implementing Vue.js backend with live demos, showcasing the modification of proxies and the use of reactive functions. It demonstrates the creation of a reactive array and the implementation of join, leave, and message functionalities. The talk concludes by mentioning the possibility of using computed properties and inviting further questions.
Why React Should Not Adopt Signals
React Advanced 2024React Advanced 2024
10 min
Why React Should Not Adopt Signals
Today I want to talk about why React should not adopt signals. By adopting signals in React, we can automatically track dependencies for effects and memos, leading to more efficient component rendering. Accessing specific parts of the JSX that read signals allows for fine-grained reactivity across component boundaries. Adopting signals in React requires migrating to single execution components, which only update specific parts of the application. This can become complex when dealing with components that read from different signals. In contrast, React assumes everything can change and enforces this assumption through linters and compilers, leading to more robust code and easier updates. If you're interested in signals in React or need performance improvements, let's chat!
Build Your Own Reactivity: A Deep Dive Into Signals
JSNation 2025JSNation 2025
28 min
Build Your Own Reactivity: A Deep Dive Into Signals
Karl Vorden introduces signals for reactivity in JavaScript, aiming to demystify its implementation for better understanding. Signals in JavaScript provide efficient reactivity by updating only the necessary code without extra work. Different frameworks offer signal implementations like createSignal in solid JS, resembling React's useEffect but functioning differently. Vue signals are called refs, created with the ref function, returning an object with a value property. Define effect functions for tracking changes and execution in reactive signals. Explore computed functions for complex operations within reactive signals. Beware of pitfalls with conditionals affecting signal execution.

Workshops on related topic

Build a Universal Reactive Data Library with Starbeam
JSNation 2023JSNation 2023
66 min
Build a Universal Reactive Data Library with Starbeam
WorkshopFree
Yehuda Katz
Yehuda Katz
This session will focus on Starbeam's universal building blocks. We'll use Starbeam to build a data library that works in multiple frameworks.We'll write a library that caches and updates data, and supports relationships, sorting and filtering.Rather than fetching data directly, it will work with asynchronously fetched data, including data fetched after initial render. Data fetched and updated through web sockets will also work well.All of these features will be reactive, of course.Imagine you filter your data by its title, and then you update the title of a record to match the filter: any output relying on the filtered data will update to reflect the updated filter.In 90 minutes, you'll build an awesome reactive data library and learn a powerful new tool for building reactive systems. The best part: the library works in any framework, even though you don't think about (or depend on) any framework when you built it.
Table of contents- Storing a Fetched Record in a Cell- Storing multiple records in a reactive Map- Reactive iteration is normal iteration- Reactive filtering is normal filtering- Fetching more records and updating the Map- Reactive sorting is normal sorting (is this getting a bit repetitive?)- Modelling cache invalidation as data- Bonus: reactive relationships