1. Introduction and Recoil.js Overview
Thank you for having me. I'm excited to chat. I just moved to Prague and the weather is much better here. I was listening to your talk about Recoil.js. Can you tell us about yourself and your work at Facebook?
Thank you so much for having me. It's definitely exciting to get to chat. I regret that the place I'm staying doesn't have a fireplace. We'll just have to pretend. Yeah, I just moved to Prague now because I've stayed during the holidays in Romania and now I'm in Prague. But here it's much better. I'll have to say the weather is much better. I'm so happy to have you here.
I was listening to your talk about Recoil.js and it's so nice. I mean, there are so many state management solutions out there, right? But Recoil, since it's coming from Facebook and from you especially, it's really great to see that. But before anything, could you please give us some details about who you are, what you do and what's your daily job basically?
2. Dave McCabe's Work on Performance Analysis Tools
I have worked at Facebook for a few years, focusing on performance analysis tools. I build tools that are based on multiple measurements taken from production and aggregated into statistical distributions. These tools allow for different analyses to determine the variables affecting app performance.
So my name is Dave McCabe. I have worked at Facebook for a few years now and most of the work's been focused on performance analysis tools. So you've probably, most of you've used the profiler in your browser where you measure what's taking so much time and why things are slow and where the code is spinning and sign that kind of thing. I spend a good deal of time building tools that are like that, but they don't just take a single measurement. They're based on many, many different measurements that have been taken from production and then aggregated. So if you can imagine a profiler like that, but everything that you see is a statistical distribution instead of just a single measurement. And you can do different analyses based on what variables might be affecting performance of your app.
Recoil Status and Comparison with Redux
You can do different analyses based on what variables might be affecting performance of your app. Recoil was extracted out of an app with specific needs and made into a separate library. If you're looking to replace Redux, consider using React only or with React and Relay first. Recoil is actively maintained, with recent improvements and more on the way. It's being used by many things inside Facebook, but it's still considered an experimental project.
And you can do different analyses based on what variables might be affecting performance of your app. So whether it's the type of device that somebody's using or things about the user, maybe something that have a lot of friends, you know, different types of things like that, or whether it's affected by a code change, configuration change. So I spent quite a bit of time building stuff like that and Recoil kind of was extracted out of an app that, it had certain pretty specific needs. And we decided to kind of pull that out and make it a separate library.
Wow. So, so many things. I'll not say anything about myself now. I would like to just shut down the camera and just pretend that. Why do you say that? I don't know. I don't have that. Cool. So, since I don't see any questions on the discourse, If anyone has any questions, just address those and we will discuss. But I have some questions prepared.
OK, great. And the first one is that I saw a couple of times on Twitter, especially is the following. Is this meant to replace Redux? I would say that your first choice if you're looking to replace Redux is to see if you can just do what you need with React only or with React and Relay. And there's actually a lot of advantages to that if you don't have a separate system. But I would say that if you're hitting certain performance limits with that in particular situations that we can talk about with Redux, then Recoil might be a good option for you. Great. Now I see a question coming from Jordi, but it also came earlier from BKG. They are saying that what is the status of Recoil? It seems to still be in beta. It seems like it would solve our problems, but it's hard to convince others because it's a beta product. What are your thoughts around it? Yeah. It's being actively maintained. We actually just put out a release about a week ago that has some really nice improvements and more is on the way. It's being used by a lot of different things inside Facebook, so definitely we depend on it. It's not going to disappear. But we consider it to be an experimental project because it's not something where the company is saying, we totally endorse this. This is what everybody should use, which is the case, for example, with React. React has a very, very high quality bar and it should work for basically any app that you want to write, we think you should do with React.
Recoil Updates and Selector Implementation
Recoil is more of something that could be useful. Recoil was bumped to 0.2, with improvements in selectors and performance. Selectors in Recoil can have dynamic dependencies, allowing for a flexible data flow graph. The basic way to implement selectors is to have a cache of dependencies and their corresponding values.
Same is true of Relay. Recoil is more of something that could be useful and if it's useful for you, then we're very happy to make it available. But what its really long-term future is unclear.
All right. Yeah. I mean, I can look at Recoil and say this is definitely the answer, capital T, capital F, you know what I mean.
Regarding those little updates, I saw recently that Recoil was bumped to 0.2, right? Mm-hmm. And can you just please tell us more about the improvements that you guys did or you did in general and what bugs were fixed in general? Yeah. Sure. The two main improvements in 0.2 were a new implementation of selectors that is much more robust and fixes a bunch of bugs that probably most people wouldn't have hit, but you could. And then it's a lot faster if you have a really large number of atoms. So if you have thousands, tens of thousands of atoms, it would bog down. And now that should be a lot better, which we actually use in certain apps that use recoil. We'll have, like, let's say you have a document and every element in the document is represented by an atom, right? So that's the kind of thing that it's meant to be good for and that actually works a lot better now.
Regarding the selectors, it's, so something that's unique about recoil selectors is they can have dynamic dependencies. So every time you execute the selector, it's not that it has statically declared a set of other atoms or selectors that it depends on. And just to maybe step back, if people aren't familiar with it. A selector, the way we think of it is a function, it's a pure function of some other state that just has information about what state it needs so that when that state changes, that function will be reevaluated. So that, like, the components could subscribe to state, but it can also subscribe to a function state, if that makes sense. So you end up with this graph, this, like, data flow graph, and things are flowing from state down through these functions and into components. And most things that do something like that, the shape of that graph is known ahead of time. But in recoil, it can actually change. It's a function, technically, of the state, so it's not, like, chaos. At a given state, the graph will have a particular shape. You discover that by evaluating the selectors, and then when they run, can say, I need this data, I need this data. But that can be conditional. So in one state, it subscribes to some data, and in a different state, it does not. So far, so good. The basic way that you would want to implement selectors is that, like, if you were just, you know, sitting down, thinking how to do this, you would have a cache where the entries are, like, sets of dependencies. So these were my dependencies, they were in this state, so here's the value that I got.
Dynamic Dependencies and Selector Execution
Dynamic dependencies in selectors can cause issues with asynchronous execution. Recoil separates the execution of a selector from the evaluated value at a specific state and time. This fixes edge cases with async selectors, making it a robust feature.
That doesn't actually work if you have dynamic dependencies, because a particular evaluation of a selector, if it's asynchronous, the set of dependencies it has, and hence the cache key it should have, will actually change over the asynchronous execution of that selector. And so basically it's just this big kind of redo of all that to separate those concepts. You have the execution of a selector and then you have the value that's been evaluated for a particular state at a particular point in time. And those are two different things.
A lot of things happen, actually. The upshot of that is just that there was a lot of edge cases that could happen with async selectors that are now fixed. So that should be a really robust feature.
Selectors and State Separation
Recoil is based on the idea of separating state into individual atoms. Unlike Redux, where all state is stored in a single unit, Recoil allows for separate atoms that can be updated independently. However, when using selectors, it's important to be aware that all selectors are evaluated whenever any state changes. To avoid unnecessary updates, it's recommended to break up the state into smaller pieces and use Recoil's API to update them together as a single unit.
OK. So related to selectors, Jyrock94 asked a question, are there patterns or gotchas when creating selectors that would cause performance hits or unneeded renders? Yeah. I think the main thing to look out for that is that recoil is based on the idea that you separate out your state into little atoms that are individual, compared to if you're thinking about it the way you might think about it and say Redux or some other systems, you have a big black store with all of your state in it. It's one unit, and it is updated atomically. And then you have selectors that are pulling out little parts, like that this bit is going to be used by this component. This bit is going to be used by this component. So they're selecting them. Right? That approach eventually hits a scaling limit because as you have in selectors, whenever any state changes, you have to evaluate all of those selectors again to see whether the things that are downstream of them need to update. So you don't want to wind up in a situation like that, and recoil doesn't optimize that at all, if that's what you're trying to do. So it will not bail out early if you have a selector that's value doesn't change. So the way that you want to do it in recoil is to already take the things in your state that would independently be updated and separate them out into different adders. That's the main thing that I see people running into. So you want to break up the state into little pieces and then recoil does provide you with an API that will let you update them together as a single unit.
Recoil Update and Performance Improvement
Recoil 0.2 introduced the hash array map tree plus package, which improves performance by implementing a data structure that allows for efficient copying of segments instead of the entire structure. This is particularly useful for large numbers of atoms. It's interesting to note that this approach has similarities to the persistent data structures used in Clojure script. These third-party libraries, like Baobab JS, offer valuable implementations that contribute to the success of Recoil and other libraries.
Great, I have another question about the new update. So recoil previously was dependency free, right? There are no third party dependencies and 0.2 you've added the hash array map tree plus package. Can you please expand on that? And what is the purpose of it? And why does that help?
All right, right. Yeah. So that goes back to, I said there's two changes in 0.2, I talked about the first one. The second one is just the improved performance. And that just comes from having a data structure that lets you do something that's like an as if copy, like you're taking a big map or a big set and copying it, but without actually having to do that. Because that will eventually slow you down a lot if you're just taking a built-in map or something and copying it. And so that library implements a data structure that lets you, basically if you think of this is probably easier with pictures and if you Google for like hash trees, you'll see these, but basically what you want to do is divide up your structure into sort of segments that are then in a tree. And if you want a new copy of the whole tree, you just need to copy the segment, where the changes happen and like all the nodes that point up to that. That's the basic idea. And everything else, you have a new tree, but it ends up, most of it goes down to the same sort of base level structure. And so that's what that implements. And yeah, it's just for improved performance. If you have a really large number of atoms.
This actually reminds me in the past, I was looking at Baobab JS, which is, are you familiar with Baobab? I don't know that I am. Why don't you talk about it a little bit. Like the tree. Yeah, exactly. So it's based on indexes and yeah, it's basically, it's like a tree, right? And you have leaves and whenever something will update, we'll just trigger down the road. So whoever is listening to those changes will receive an update. But it's so cool to see great and like so valuable third-party libraries, which are really tiny in size and that can do so many good things for recoil and also for other libraries. Because it's an implementation.
Advantage of React Context Provider over Recoil
Compared to Recoil, using React and a React context provider can efficiently handle shared data within a tree. It has minimal overhead and ensures compatibility with future React features. However, specific advantages may depend on the context and communication between components.
What is the advantage over React context provider? Compared to what? Compared to Recoil, of course. Ok, well I think that, for most things, for most apps you don't need to involve another library. So you can just do that with React and a React context provider, that lets you have some data that's sort of shared within a whole tree that is efficiently handled by React. There's not a lot of overhead to doing that. And then, it will work with different, potentially future React features. So, like if you look at things that are coming down the pike in React, like server components, that type of thing. If you're using built-in React features, you are guaranteed to have compatibility with whatever new features come out. If you're using some other library, including Recoil, it might or might not be compatible. So, I wonder if they have something more specific in mind with their question, but that's just sort of what comes to mind. Yeah, we will wait for René to pose there. But, yeah, it's more like maybe the communication between components. We are waiting for him just to add more details, maybe.
Server-side Rendering and Atom Unloading
Recoil supports server-side rendering (SSR) through the initialized state API. You can manually delete atoms using the useResetRecoilState hook, but there are upcoming changes to automatically free atoms. Recoil.js is best used when you have multiple pieces of state that affect distant leaves in your React tree.
Another question that popped two times, actually, was the state of the server-side rendering support in recoil. Guido actually asked this, and Buhtargac, hopefully, I have not misspelled it. If you can add something about SSR? Yeah, we do support it. I'm not actually aware, I haven't heard from anybody using it, but we do get a bug report every now and again in that scenario, so I assume that people are using it, and we try to fix those bugs. So, basically, recoil provides an API that you're probably going to want to use if you're doing this called initialized state, which is a prop of the recoil route. And when you use that, it uses that state on that first render. And so that's what's going to be used for SSR.
Great. Another question from JROK94, can you unload atoms? If you are dynamically creating atoms by id, and you no longer need any of them, are they trapped in memory? Just before you answer, I actually went to recoil.js docs, and you are actually mentioning there that it's something that you are going to work in the future, but maybe you can say more about that. Yeah, so currently, you would do that by manually deleting them with a hook that is called useResetRecoilState. That will clear out that value. It's sort of resetting it, but it's really deleting it, resetting it to the default value. And so that's what you can do at the moment. And then we have some changes coming out soon, hopefully, that will automatically free atoms. So you'll opt into it on a per atom basis. You'll say, I want this atom to be garbage collected, basically. And then when it's not being used by any components, it will get deleted. And we're using that internally. And hope to release that open source pretty soon. There is a slight API change. So there's going to be one release where you're going to get a warning that you need to like change a thing. And then another release where that feature will be turned on. Really small change, shouldn't affect most apps actually.
Amazing. Another question is, where can I use recoil.js? And in your opinion, what's the best use case of it? If you can expand just a little on that as well. Sure. Basically, you want to use it in situations where you have a bunch of different pieces of state. Like an indefinite, not like a fixed number, but some variable number of different pieces of state that affect sort of distant leaves in your React tree. So the tree, the basic assumption in React is that most updates are either going to be small or big. So either you're like updating one button because you clicked that button, or you're going to a different screen and you have to re-render everything.
Handling Updates in React and Recoil
In most apps, React efficiently handles updates in most cases. However, when you have frequent updates in distant parts of the tree, subscription-based updates from state outside the tree may be more suitable. Start by building with React alone and consider adding Recoil if needed.
In most apps, most updates are in those two categories, and both of them are very efficiently handled by React. Where it doesn't work so well is when you have things that are updating quickly, but they're in distant parts of the tree. Because it's not the whole tree. It's not one part, but it's like over here and over here. That's where you want those sort of more subscription-based updates from some piece of state that's not in a particular part of your tree. So you can use it in situations like that if you need it. But I'd really suggest you try to just build with React, and see how far you get. And then you can add Recoil as an extra ingredient if you hit a limit.
Relay, Refreshing Async Selectors, and Recoil
Amazing. Thanks for the tip. I'm pretty sure that whoever is listening now and will listen in the future, they'll take a look at Relay as well. I have another question from Mr. Oz. Is there a better way to refresh async selectors than using request ID atom, like request ID? It's request ID plus one, which returns request ID plus one. That's exactly the way I would do it. If that's converse, you can take that whole pattern and wrap it up into something that will generate those for you. I think we actually have one of those. I'm not sure if it's open source, but it's very easy. You can write that once and that's the way to do it because that maintains the concept that a selector is a pure function of some state. When you get into things, like if you're going to do time travel debugging, or something like that, or just looking at the system, everything is a pure function. It doesn't vary over time. You're explicitly modeling in time, but then that's part of your explicit model that you could manipulate. Does that make sense?
Yeah, I remember when I first got started with React, which was almost eight years now, there were mix-ins, there was no context API. There used to be a context API, which was hidden somehow, and you need to dig really deep into React to internals. But I remember we had such a big tree that at the end, we had so many properties that we're sending down the road and basically cascading those. And we had so many unnecessary renders because it was in the middle of the tree, the component was basically just a proxy for those properties, because we are using the methodology HATEOAS, which is basically like an API Explorer, so an API response will give you more endpoints where you can fetch more data based on the current resource. Basically, just think about HATEEOAS as a user's endpoint API that will give you user 1, 2, 3 URLs that you can fetch forward. So we are having basically a representation of the API by components, React components. And I remember that everything was really not that performant, so we had to do component update tricks and pass somehow on the global state state, but then of course Flux and Redux appeared, and this state management solution, and nowadays it's Recoil, which is looking really promising. It's really easy to use. I just went to the docs and I could really easily digest almost everything, not the internals yet, but the overall API seemed really easy to go through. Speaking about getting started.
Recoil in React Native and Rewriting Applications
React changed the way we think about user interfaces, leading to a Cambrian explosion of ideas. Recoil can be used in React Native, although it's not used internally at Facebook. It's great to hear that you're a fan of React Native. Rewriting a large application is challenging, so it's important to measure if Recoil works for your specific use case.
Yeah, sure. I was just going to say thanks for that, and I'm happy to hear that it's easy for you. It's been very cool to see since React, React really changed the way that one thinks about user interfaces. There was a paradigm that was basically set in like the 1970s with the Xerox stuff, object-oriented, that whole way of looking at things that was carried through basically until React was invented, and now it's then this Cambrian explosion of people figuring out how to actually use the new paradigm effectively. It's been fun to see all the different iterations of that.
What were you going to say? Since I'm a really huge fan of React Native, am I able to run Recoil in a React Native environment?
Yeah. It's something that we don't use, but that is supported. So, there's some folks in open source that have contributed to that and are trying to maintain that so that it works. It's part of our test when you release. We make sure it works on React Native and that kind of thing. So, in theory, yeah, it should work no problem in React Native. So, happy to hear that you're using that technology as well.
Yeah, I'm a huge fan. I actually had access to it since it was in private because I was blessed that someone went to React.js conference when it was announced in 2016. I'm playing with it since then. I truly love it. Actually, we are using it in Skype as well. So, we're using React Native and Electron. For state management, we have our own solution which is open source. It's different compared to recoil. But, yeah, this is what worked for us. And it's pretty hard nowadays to revamp everything or rewrite everything, right?
Yeah, definitely. Because it's a pretty huge application.
Yeah. And rewriting is not in general something really good. So, yeah.
Yeah, it takes an enormous effort to do that.
Yeah, exactly. So, does it work? You need to also do some measurements. Does it work or not?
Getting Started with Recoil and Production Usage
If you're looking to get started with Recoil, you can find documentation and helpful videos on recoiljs.org. There's also a developer who has created learnrecoil.com, where you can learn everything you need to know about Recoil and even recreate Excalibur using Recoil. As for using Recoil in production, it's important to weigh the benefits and risks for your specific app. While it's an experimental project, it's actively used by Facebook and will likely continue to be supported. It's reassuring to know that open-source projects by Facebook are actually used in their own apps, even in an experimental capacity.
Speaking about getting started, maybe there are people watching us that would like to start or getting started with Recoil. Do you have any examples or good practices that people can follow or look at?
Yeah, well, there's a website. If you go to recoiljs.org, there's documentation on there. Then if you click on external links, the section of that website, there is a link to some videos that somebody has made actually that are pretty high quality and actually walk you through how to make a drawing app with Recoil and I think that's a pretty good introduction to using it. I recently came across learnrecoil.com. Yeah, there is a developer that's, and everything is for free. He's going through everything that you need to know about Recoil and he's actually trying to recreate Excalibur in using Recoil. I think that's probably the same thing that I was referring to. So that's linked to from the Recoil website. Exactly. And yeah, it seems like really good, good work.
Let's see if we have any other questions. Moving to Basecamp, Q&A. Another question from Dry's Capone. I think we discussed it, but just to ground this up, should we be worried about the experimental flag? Can Recoil be used in production? I think you need to weigh the benefits and risks for your particular app. It's not like it's going to vanish. The code that's out there you need to use. We use it a lot internally. Proportionally, because Facebook is so big. It could be a tiny fraction, but still be a lot of different apps. But we use it in a bunch of places, so we have a dependency on it, and we'll probably continue to support it. But it doesn't have the same level of support as something like React. So I guess I can't give a definitive answer, but that's sort of what the status of it is. There's a bunch of people that work on it. It is kind of a side project for all of us. But we use it for apps that we need to keep running, so it's not going to go away in the foreseeable future. Yeah, it's really nice to see that everything that's open source by Facebook, it's actually used inside a Facebook app. And this means a lot because even though it's experimental, it's used in production anyway, even though it's A-B-tested and stuff like that, but it's something that it's in the wild, how developers used to say. Another question came from M. Botis.
Recommending Recoil for Beginners
If you're starting out with React, just use React and you can get really far. For most apps, that's all you need. Don't worry about other state management systems like Redux or Recoil. Facebook.com is built entirely with React. If you need to load data efficiently, you can use Relay. Only consider Recoil if you encounter performance bottlenecks that can't be resolved in other ways.
Botis. Would you recommend recoil for beginners or rate or have them learn the others first? I think by others means React state. Right, well, yeah. I think that if you're starting out with React, just use React and you can get really, really far. And for most apps, that's all you need. So, I would say don't look at, you don't need to worry about other sort of state management systems, Redux, recoil, all that. These are for pretty specialized things. If you look at Facebook.com, it's all just in React. Like, you know, you can make a really, really complex app. And in almost every case, that's everything you need. And then if you need to load data efficiently from the server, you can add it in relay. And if you're in a case where you hit some, like performance bottlenecks, you can't figure out any other way around, then you could think about doing recoil.