Folks, who of you still use React 16 and React 17? Could you send your React current React production version into the chat? I'm just wondering, who of you are on 18? Who still uses 16? Who still uses 17? Could you send it into the chat? 17, 17, 18, 18, 18, 18, 18, 17, 18. Oh yeah, so, nice. A lot of you are already on 18. I just keep asking these during every workshop that I do and I just see how more and more people upgrade to 18. This is fascinating. All right, but a few of you still, ooh, AngularJS 1x. Okay, I'm sorry for that. This, my condolences. Anyway, a few of you are on Rect 17 and with Rect 17, this is even tricker because with Rect 18 you could at least see, you could at least notice that, hey, Passive Effects Reactor and Passive Effects and the Passive Effects took some time. But if you use, if you, for some reason use Rect 17, or no, sorry, not for some reason, if you use Rect 17, if you haven't upgraded to Rect 18 yet, what would happen, okay, I'm gonna switch to Rect 17, use Rect 18 false and comment out with the same part that does not exist in Rect 17. So if I switch to Rect 17, I get this warning that I custom coded and I re-record the same interaction using Rect Profiler, oh, and stub, wait now, oh, reload. Oop, and stub. Wait, this. Oh no, I did not switch to, what did I do wrong? What did I do wrong? Oh yeah, right, I need to restart the VEED server because it still uses Rect, Rect 18. So if I switch completely to Rect 17 in this app, or if you are still using Rect 17, if I try to record the same interaction using Rect Profiler, what I would see, I would see the render duration, but I would not see the effect duration at all. And this might be very confusing because unless I go in and directly match what I see, hold on, unless I go in and directly match what I see in the performance pane, with the profiler pane, and unless I notice that the profiler pane tells me that it's 25 second, sorry, milliseconds, but the performance pane actually tells me that the interaction took 350 milliseconds. Unless I notice this, what could happen is I would look at this component and I would try optimizing the most expensive components like we were doing in the past two hours, and that would not give me any benefit. Because this is only responsible for like 10% of the whole interaction cost. So this is why, this is why, there in the flame chart, there's one more step that I've been skipping so far. Which is whenever I record some interaction using Rack Profiler, sorry, using Chrome DevTools, what I need to check is, I don't only need to check whether it's mostly React code or mostly something else. I also need to check whether it's React rendering or whether it's React effects. And I'm going to switch back to React 18, yarn add, React 18, yarn start, and I'm going to record this again with React 18. This is a wrap, F, and stop. And I would have to look through my recording and try to figure out what exactly is happening here and where exactly React spends most of its time, if it's in rendering or if it's in effect. So, let's see what's happening here. We get the keepers event, the keepers event triggers the text input event, input, et cetera. Then I get some calls from the code mirror, anonymous, text, area input, poll, yada, yada, yada, yada, yada, like all this code, I don't really care about all these functions, they just run the child functions, right? They do not spend time, much time in their own, it's like, they're mostly just structures for other functions. So, I keep going down, I see some anonymous from index JS 6. All right, this does look like my code. We get some React, it's some React and we get some event handler. And then we call save node, then we call save node again, and then we finally get to React code. And so save nodes splits into two rectangles, it calls two functions, one dispatch set, state and another anonymous. If I keep going further, the second anonymous, so it's some React Redux code, and then again I would get to React on development. And so at this point, if it's just, if it never gets to React codes, then it's these brands, then it's mostly non React code, then I need to figure out what's actually happening there. What are the most expensive functions? But as long as I see the React code still taking most of the time and it's still taking most of the time, 50 milliseconds plus 315 milliseconds. It's almost the full duration of this keypress event. As long as I see this, I could just look at the event, I could look at the name functions and I could figure out what exactly is happening in the React code. And here is a very nice cheat sheet that I have for this. A React internal reference. This is true for React16, React17, React18, whatever React version you use. So render root sync means that you, the director is busy rendering some components. If you scroll farther down the flame charts, you could even see these components. You could see the nots list component being rendered. That just the nots list function being called, right? You could see the not button being rendered. You could see some React markdown being rendered. Button group buttons. So you could see all this. You could see all the components that are actually being rendered farther down the flame chart. Then, commit layout effects is the part that runs, use layout effect component did mountain and component it updates. We don't really have it here, it seems like. We have the commit root. Oh no, we do have it. Here's commit layout effects. We also have commit mutation effects, which I think just update the DOM. I'm not fully sure. I don't fully remember, but like, it's never a bottleneck. We have commit layout effects. It runs some layout effects and it's very cheap in this case. And then we have uncommit root, which is something else again. I don't care about it. Then we have the function that's called flushBaseEffect, which in the reference it's the function that runs useEffect. And so what this, what, when I see this, and when I see the flushBaseEffect is responsible for the biggest chunk of the recording, what this means is I can't go to React Profiler and figure out what's happening here. React Profiler would not show me this. Instead I need to keep going further down the flame chart until I leave the React code and stumble upon the actual effect that is getting executed. And it's quite easy to find, it has a different color. And if I find it, if I click it, I would see that here, here's this effect. Use effect, save nodes to local storage. All right, so we have found the culprit, we have found the expensive effect. How do we make it cheaper? So, at this point, there are two ways to analyze it. The first thing I could try to figure out is why do these effects rerun? Does the effect actually need to run or is it just its dependencies rate that's changing unnecessarily? Maybe we're also passing some function that changes every time.
Comments