Video details

Handling Data at Scale for React Developers – Tejas Kumar, React Summit 2022

React
09.12.2022
English

React Summit 2022 #ReactSummit #GitNation Website – https://reactsummit.com/
Follow the link to watch the full version of all the conference talks, QnA’s with speakers and hands-on workshop recordings → https://portal.gitnation.org/events/reactsummit-2022
Talk: Handling Data at Scale for React Developers It is very difficult to scale modern web applications to millions of concurrent users. Oftentimes, we've got to provision and consider in-memory Key/Value stores, search engines, analytics engines, and databases, all while preserving traceability through the layers. This talk expands on the technical details of web apps at this scale, and offers a simpler way to achieve the same effect without the technical hassle.
This event would not take place without the support of sponsors:
🏆 Platinum Sponsors Ag Grid → https://www.ag-grid.com/ Toptal → https://www.toptal.com/freelance-jobs Rangle.io → https://rangle.io/
WPEngine → https://wpengine.com/ Vodafone → https://careers.vodafone.com/
🥇 Gold Sponsors StackHawk → https://www.stackhawk.com/ Bitvavo → https://bitvavo.com/ Ionic → https://ionic.io/ JetBrains → https://www.jetbrains.com/webstorm/ Kontent by Kentico → https://kontent.ai/ Decentology → https://www.decentology.com/ Xata → https://xata.io/ Docker → https://www.docker.com/ Shopify → https://www.shopify.com/careers Wix Engineering → https://wix.com NearForm → https://www.nearform.com/ Focus Reactive → https://focusreactive.com/ Sanity → https://www.sanity.io/ Snyk → https://snyk.io/ Contentful → https://www.contentful.com/ Nx → https://nx.dev/
🥈 Silver Sponsors Firebase → https://firebase.google.com/ Callstack → https://www.callstack.com/ Mercari → https://about.mercari.com/en/ vpTech/ → https://careers.veepee.com/en/vptech-2/ NativeBase → https://nativebase.io/ Stream → https://getstream.io/ SiteGround → https://www.siteground.com/ Yoast → https://yoast.com/ Novermber Five → https://www.novemberfive.co/ Twilio → https://www.twilio.com/ahoy BCGDV → https://bcgdv.com/ Fullscript → https://fullscript.com/ Utopia Music → https://utopiamusic.com/ SISU → https://www.sisu.tools/

Transcript

I was totally playing that guitar. Hi, how are you? Full from lunch. Satisfied? Ready to take in some more knowledge and influence formation and fun react things? Like three of you are awake again. How are you feeling? You're ready to take in some stuff off by one errors? Anyway, hi, nice to see you. I'm I used to tell people I used to tell people it's like something, but now I say advantageous was contagious. Anyway, so I'm the Director of Developer Relations at Zara. Look at this beautiful thing. That is my favorite slide and also one of my five slides I have. Okay, we're going to be writing a lot of code in this talk and learning properly. This, by the way, was by Sara Vieira. She's here. She's doing the last talk today. So catch that if you want to learn how to do three D stuff. But that's not what we're here to talk about today. We're here to talk about handling data at scale for React developers. Handling data at scale for React developers. What does that mean? This sounds like a very abstract marketing talk. And the answer is because it's not a marketing talk, but it is abstract on purpose. So then I can change it at the last minute as I always do. Okay, but let's get more specific with that and actually look at a diagram of what we mean by data at scale. To do that, I'm going to use an amazing tool called Excalibra. How many of you heard of Excalibur? Yeah, if you want to apply Excalibur yeah, for sure. Data at scale. This is what it looks like. So usually you have a React app or React UI, let's say. Right? Is the text okay? Can you all see? Yes. Good. I knew I just asked. And what we're going to do is usually have a React UI that talks to an API that let me zoom out a little bit. That then talks to a database. And these connections usually look a little bit like this. This may be oversimplified, but that is most applications. Is this at scale? Probably not. This is like a single host database and so on. At some point you're going to experience like, oh, we're growing, and performance is important. So what do you do? You probably will distribute your API. Having a single point of failure is usually a no. So what you'll do is you'll do that and you'll have multiple APIs that can fetch multiple times and whatever, and you can load balance between them. And then you're like, this is cool. But if you're successful, what do successful things do? They grow. So if you grow, you're going to be like, oh, no, our database is now the bottom. Like, let's make it, let's scale it. So you'll scale it vertically, and this vertical scale usually means like, adding memory, adding disk space, adding stuff. And it gets quite expensive. You eventually build a supercomputer. Or if you want to scale your database the other way, you scale horizontally, meaning you have maybe a primary instance and some replicas. So when you get data, it spreads out across the replicas and so on and so forth. But then you're going to grow more. And we're talking about data at scale. So it's important to establish this context. You're going to grow a little bit more. At some point, you're going to be like, wait, our database is still reading from it is slow. And that's because usually databases read from disk. Disk by design is not as fast as what? Memory. So let's now I've had this conversation like at least 50 times in the past week. That's a lie because I'm a public speaker. I really haven't. But you know how it is. So you'll add some type of in memory database just to read from it faster. This will probably be distributed as well. And so now your app will talk to that thing to get data fast. And if it's a cash miss, then you read from the database. Okay, this is close to what things look like at scale. I think Kensey Dodd's website has something like this in the back. But as you accumulate now data volume, what is the one common feature across things with a ton of data volume? Search. So GitHub TikTok, instagram. Eventually, when you get enough data, you're going to need search. And so now it gets complicated, right? Because your app can read from the search engine, but it's going to be empty. You're just like, okay, nothing's there. You'll need to find a way to replicate data from your database into your search engine, probably in real time with some type of consistency. People will use a tool like Kafka or something like this. And so you'll send your data there, and this will replicate your data in the search. And now everything's connected. If you want to take a photo of that, that is a good representation of what most data infrastructure looks like at scale. Is that what we're going to be talking about at this talk at React summit? This is what I want to establish with this diagram. For the sake of this talk, we're going to make everything with a dashed line, someone else's problem. This is about react. This is about handling data at scale in React. Okay, that is very important that I tell you that. So now I want to talk to you about handling data at scale in React, specifically about data fetching. And so that means how can we do now there's something to be said for client side rendering, service side rendering, and so on. What I want to talk to you today about is three ways to fetch data in React. This has been talked about a few times. This is nothing new. But before we do that, I need to preface this talk is about what I've learned and what may be useful for I think it will be useful for you. But you usually want to lean on libraries that are battle tested, unit tested, even, that handle edge cases that we cannot foresee. Is that clear? So the purpose of the stock is not you should be doing it this way, use this in production. It's more I want to teach you how stuff works on the hood so you understand. So we're all a bit we come away with something that we know. Okay? So with that, there's three ways to fetch data and react. This is the prevailing three ways. Number one, probably the most common is you render your component, then you fetch. You have a component use effect fetch, then set state. This is fairly common. How many of you do that have done that? At least one. Yeah. Okay. The whole room. The next way is fetch, then render. And you see this in some libraries. Like next JS, you have like you export getserverside props. You'll fetch on the server and then you render your component. There's something to be said for that. It's arguably faster. Why? Because you start your fetch way earlier before your component rendering begins. And so then as soon as that promise resolves, you set it in state. You're good. The third way is render as you fetch. This is made possible through the new concurrent features in React 18. And we'll spend the bulk of our time writing code with that specific way to understand it. But as I said, the react team is very clear. Don't do this in an ad hoc way, but use the library. It's for the best. Okay, that said, let's just do it now. Just once. Okay, so with that that's my last slide. Let's just code. I like coding inshallah the Internet works. All right, so we saw a diagram. What I want to show you is an app. We'll have an app fetch data in these three ways. The app let me just start my dev server here. The app is we're using Parcel, just because for me, it's really great for demos. Sorry, yarn, parcel SRC index, HTML. This is going to bring up our app. And what we have is a jokes app. So these are developer jokes, classic curated by the one and only Shrudi Kapoor, by the way, shout out. She's a really valuable member of the community and the team, and if you don't follow her, you should. The reason she's on this is because she curates a collection of developer jokes. For example, how do you comfort a JavaScript developer? You console them. Okay, I just stole it from here. So what we're going to do real quick is fetch data three ways. Okay? We'll do it the way we all know first. So our app, we have our React app using create root. It's a new thing. We have our app component that renders. As you can see, the actual elements here, the heading, the jokes and so on. And lastly, we have a jokes component, this thing which is supposed to fetch data but doesn't. So we'll fetch data three ways and then we'll talk about what we learn. To do that, I'm going to get my data from here and fetch it immediately. Again, intral network, please. Awesome. That's enough. You know what I think the network depends on? Never mind. I was going to do something awesome, but now you don't. Okay? So I'm going to get a code snippet here in JavaScript, fetch this in my app, just client side, as you know. So we'll do something like this, and when search changes, just refresh. We'll paste the code snippet. I'll add a filter just for fun, where the joke contains search. And then instead of console logging the response, I will set jokes. I will not do that. I will set joke to result records. Okay? I'm just fetching data. You're familiar with this? I'm not spending too much time on this. And just like that, we have jokes from an API. So what is the most used language in programming? Profanity. Ha ha. It's actually funny. Does the search work? We can use words like, okay, we're fee not, but okay, married life, a developer wife. Right, 100%. So we're rendering the component then fetching. Okay, this is fairly common. If we walk through the code briefly, we have the jokes in state, we fetch and we set state and then everyone's happy. Notice we're not handling loading states yet. We'll get to that. This is the traditional way. What about fetch then render? You see this less common in userland. I've spoken to some of you and you're like, what is that? Essentially the gist of it is you start fetching early so that your load time is reduced. And this helps if you're loading a component with react lazy and you're importing it dynamically. Then as soon as the component is imported, it fetches immediately and then renders. This is actually fast. In our case here, we have 20 minutes. So we're going to be working with one network hop. But in cases where you have multiple, this really helps you avoid network waterfalls. Meaning you have one request, you wait, you have another request and you wait. And it's like this waterfall. This is render than fetch. Let's do fetch, then render. So what we're going to do is we're going to take this whole code snippet thing out of use effect and put it here in module scope. And you're like, how can this be? You don't have set jokes. Exactly. So I'm going to take this piece, put it back in use effect, and do promise, then set state. What is promise? It's my fetch call from module scope. Okay, does this look odd? Maybe because you haven't seen this much. So we don't get the dynamicism, whatever the dynamicness of the search prop here. So because we're fetching in modules, code doesn't work. It does. And it's arguably faster. Why is it arguably faster? Because we're fetching before we render. So the data is kind of ready. The problem with this, of course, is it's just going to be stale. I can't control it with props. I can. Maybe if I made promise, like a function, like get promise or whatever, sure, but it's not that common, especially if you're outside a library. And the performance benefits are, I don't know, questionable. Let's talk about render as you fetch. Okay? React 18 has concurrent features where you can start rendering a component and when you reach a component that is not yet ready, that doesn't yet have data, react doesn't render. It renders like a hole, fall back, and after that it continues down the tree. And then when the component is ready, then it renders. So it's like render as much as you can fetch while you need it and then render again. Okay, that's what we'll look at. The tool that enables this is called Suspense for Data Fetching. There's an RFC about it here. Trust the RFC, don't trust me. Okay? This talk is just condensing this with examples. But this is the source of truth and so is the React blog and the React docs. Specifically I wanted to show you suspense and Data frameworks. This is important. So learn how stuff works. Maybe don't do it yourself. Okay? This is just for understanding. Now, how does this suspense for data fetching work? Let's look at an example here. So we are already fetching in modulescope. What I want to do is create something called a resource. It's kind of like a primitive that Suspense for Data Fetching will use. And this is what they look like. So I have a function called Create Resource and I'll wrap my entire thing outside of my component in it. Okay? I'll need two pieces of state. So I'll need the result, which can be anything. This is TypeScript and I'll need the status which is in the beginning it's initial. So I have a bunch of boilerplate here that's not touching that. What I can do is promise. Actually, I just added then here and by now I have data. So data and I'll set. My state result is data records. Status state is done. I'll do the same thing for Catch. So Catch state is error and the result is in this case, it's not even data. Let me just fix that. Okay, so when the promise resolves, we're going to update our scope state in this function. What does this function create? Resource returns. It can really return whatever you want. But in this case, I'm returning an object with a function called Read. And what Red is going to do is if the state maintained in this function is initial, I can use a switch case for this too. I'm not doing that just because I don't want to. If the status is initial. So the data hasn't loaded yet. This was controversial. So I'm throwing the not yet resolved promise. Who's going to catch it? React. And then when it's ready, React will continue rendering. Okay? If the status is error, we'll throw the result instead. And if the status is done? If the status is done, I just return the result. Return result. And so React knows how to deal with this. This is what they handle. What I'm going to do now after Prettier saves is I'm going to create an initial resource and I will just create it just like that, okay? And instead of all of this set state stuff, all of this instead of jokes here, I'm just going to read from my initial resource. Like that save, let's go back to the demo. And it works. So what's the benefit of this? This is great. There are some benefits. For example, it doesn't replace well. It doesn't actually search. We need to figure that out first, right? But look at the loading state. It's instant. There is no, like, flash. More than that, if we throttle the network request just to make this back end is way too fast. I don't even know what it is. But let's throttle this instead. Let's throttle this here and now. Let's actually throttle it a lot. Let's be like 3 seconds. And now what we'll notice is we have nothing for 3 seconds. The whole app appears when the joke's part loads. This isn't ideal user experience. So instead what we can do is go to our container app and wrap just the part that needs data in the Suspense component from React. Now, if we load the page, wait, three second boom. So we can granularly control where React suspends. We can even give it a fall back here with just like that says loading, for example. And now if we reload, we have loading where we want it. But with Suspense, you can actually choose different parts of the Dom to hide. So we moved it. We now hide the paragraph. We can also hide the input field so you don't type and then it loads. This, by the way, also works on the server side, out of the box, no code changes. You shouldn't implement it yourself. Trust the library. But Suspense on the server side works exactly like this. The HTML actually pauses as it's downloading. The last thing I want to show you is now this doesn't work. Actually, let's make the search work. So we're already here. What we need to do is we'll use an effect such that when search changes, we'll recreate the resource. So we'll do Resource or just R and set R and we'll use state initial resource. Okay, that is this. Okay? And so now we'll use this instead. So when search changes, we'll set R to search as a parameter. And our create resource will accept a search which is a string. And search will be replaced here with search. Just like that. This looks great. It needs a resource, right? So we create resource in here. Okay? And so now every time the search changes, the resource that fetches data changes and our search should work. But it could be that my access token expired. I need a new one the last ten minutes so that you can't sniff them and steal them. So let's go back to my fetch call here and replace this thing. Okay, cool. And now I'm doing something wrong, aren't I? Inshallah the network isn't working again. Okay, it's 400, right? Sorry, I meant joke contains search. Oh, thank you, whoever said that. I appreciate you. There you go, default prop. And now it should be on the money. Okay, there you go. But there's a flash look. So now if I try to search this thing, if I type like wi, hey, what about I? You will hide my so look, a keystroke is an urgent update. Changing results is not an urgent update. We need a way to tell React what is an urgent update and what can wait a bit. To do that, we use another concurrent feature called Use Transition. This is a hook and this is really important, so pay attention. So you get back a couple loading and start transition from this hook. Use Transition. Okay, what we'll do is we'll wrap this set state of the resource in this, and just like that, react now knows I'm going to wait for all the urgent stuff and then I'm a fetch. So let's try this again. Let's type profit. Look at that. Wow. I can type all I want. And then there's like a three second delay and then it changes. So that allows us to more fine grainedly tell React this is important. That can wait. We can also, if we recap more fine grainedly, decide where the loader occurs with suspense. And that is render as you fetch, where React will actually pause where the data is requested and continue down the tree. And then when the data is ready, come back and render there. These are considerations you're going to have when you work with data at scale and React. Why? Because it can muddy up your UI and introduce Jank. All right, let's recap and finish. What have we learned? We've learned about the three ways to fetch data and react so far. Right. Render, then fetch. Fetch, then render. Render as you fetch. We looked at them in practice. We didn't get time to look at it in the server side, but that's a 20 minutes talk. But render as you fetch also works on the server side. We also looked at data infrastructure at scale and I don't know, I feel like it's been good. So now, last question. How do we use this stuff? You don't do what I showed you here. This is just for understanding. There is a library. Trust them. Next, JS remix or framework I should say, you usually want to lean on the shoulders of giants, as you all do. As Taz said, community is everywhere. And with that, I want to wish you happy coding and thank you so much for having me on stage today. Now, that was one well deserved applause. Did you know that I once wrote a whole software to make it look like I'm good at live coding? And you're actually doing it better than my fake software, so that's incredible. All right, we have a few questions from Slido, so let's get right into it. And also, by the way, here in this room, if you are moving between tracks, could we do so quietly so the back of the room can also hear the questions? Thank you very much. Alright, so can you use memo for resource replacement when search string changes to avoid double renders? Probably. I don't know, I haven't tried. I encourage you cry and let me know. Cool. Is there any similar option to do render as you fetch before react 18? As far as I know, no. I mean, there was some experimental builds before react 18 that you could do that, but concurrent features are new and the 18th part is because it's a breaking change, so to speak, so I don't think so. So all of this stuff that you talked about, it's in the RFC, it's in the documentation, right? Exactly. What's the status of the RFC now? Is it ready for production use? I think it's a more intent to ship instead of shipped, but the intent is there. Okay, cool. What about fetching in an event handler, such as on Click to navigate, is this render as you fetch? Could be, yeah, I think I don't really know. It's fetch then render. Thank you, Philip. He was in my workshop. He knows stuff on clicking and event handler is fetch than render. All right, well, I think these are all the questions that we had from Slido. Awesome. So let's give Tay just one big thank you.