Flarnie Marchan - Ready for Concurrent Mode? | React Next 2019

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Can't wait. ๐Ÿ‘Œ

Edit: Just watched the talk. This was excellent, highly recommend.

๐Ÿ‘๏ธŽ︎ 8 ๐Ÿ‘ค๏ธŽ︎ u/stolinski ๐Ÿ“…๏ธŽ︎ Jul 06 2019 ๐Ÿ—ซ︎ replies

Sorta related side note :

I knew Flarnie had been on the React team, and then left. I really never heard much about what she did while she was there, and she doesn't have as much of a public presence as other team members. (I was told at some point that she did mostly FB-internal work related to React.)

But, I finally got to meet her at ReactNext, and she's great! Very friendly, loves talking about deep JS and React topics, and we had some great conversations about other things during the tour. Really cool person, and definitely worth following.

๐Ÿ‘๏ธŽ︎ 6 ๐Ÿ‘ค๏ธŽ︎ u/acemarke ๐Ÿ“…๏ธŽ︎ Jul 07 2019 ๐Ÿ—ซ︎ replies

She explained the concurrent mode with React lifecycle methods. But we have hooks now, Does that mean React functional component is still applied the same lifecycle methods under the hood by Fiber?

๐Ÿ‘๏ธŽ︎ 2 ๐Ÿ‘ค๏ธŽ︎ u/qmn1711 ๐Ÿ“…๏ธŽ︎ Jul 07 2019 ๐Ÿ—ซ︎ replies
Captions
can you all hear great sounds like the mic is on are you ready for it concurrent mode whoa I know let's let's talk about concurrent mode and as Adam just said hi I'm flirting it's nice to meet all of you I work at Sheng I previously worked on reactor core I should mention Cheng is hiring I'm happy to talk about that I also love talking about JavaScript front-end react feel free to ask me questions later if you have them so let's talk about react who here likes react I think lots of people it's a react conference so I hope you like react you've probably all had some good experiences with react because it allows us to write our UI code and a declarative style we can do more with fewer lines of code it updates the Dom in a performant way Papes / browser inconsistencies lots of good stuff right but react is not perfect in fact my biggest complaint about react is a complaint I have about all JavaScript so what's the problem the problem is that JavaScript blocks the main thread so for example if I click something in a web application when JavaScript is running it's blocking the browser from responding to my click until JavaScript is finished running you've run into this I'm sure in real web applications for example if you're trying to type into a text input and you're typing typing and it does not respond you're like what's going on and the mouse might even turn into a little beach ball and that is a clue that javascript is blocking the browser from responding to us right and so we wait and for lucky JavaScript finishes running and the browser responds but it's too late we've had an awful user experience right another symptom of this problem often happens when you're trying to scroll in a web application so as we scroll through a list of items the browser may be loading in those items and rendering them with JavaScript and you can see in this example it makes the scrolling kind of janky and stuttery so it's because javascript again is blocking the main threat how do we fix this enter react concurrent mode the main idea is very simple it's that when react is running and something in like a click or an important event happens then react will yield the main thread to the browser allow the browser to handle that click or that update afterwards react can come back and finish rendering so this is great we're not blocking the main thread anymore but there's more there's additional benefits that we've learned concurrent mode can unlock for example if we can control when we run different parts of our JavaScript then we can potentially do something like pre-rendering do some lower priority work when the browser is idle so in this example there's these three buttons at the bottom to show different views if we're not clicking or scrolling the browser is idle it's not doing anything so we can use this time to calculate what those views would look like and then as soon as the user clicks we're ready to update the Dom very fast another time when pre-rendering is really useful is during the initial page load this is a time that's really performance sensitive so looking at a timeline of the initial page load it might look something like this we often fetch some JavaScript then we run the JavaScript and then we may hit a point where we need to download either more JavaScript or some data and we're waiting for that to come back before we can finish rendering with JavaScript whenever we're waiting for data this is called me an i/o bound this is another time that we could do some lower priority rendering maybe we could prepare the code for the views that are below the fold or views that are in a drop-down or a tab so pre rendering is is a really important benefit there are other benefits too so I'll just kind of sum them up so we're on the same Paige why do we want react concurrent more because it allows us to prioritize those important updates like clicks user interactions stop blocking the main thread it allows us to deprioritize work that may not be needed like a spinner if data comes back very quickly we can avoid rendering spinners at all it allows us to do pre-rendering during idle time an i/o bound time and it can allow us to smooth out animations and video playback again because we're not blocking the main threaten so I don't know about you but I need all of these things in my web apps like today yesterday even it sounds great so how do we prepare for this upcoming feature and get a deeper understanding to get a deeper understanding I'd like to bring all of you along on the story of some early experiments that I did at Facebook with reacts concurrent mode in kind of preparing it for the upcoming release so how do you prepare a feature for something like react that is so wide we use Houston effect so many applications how do we get this ready and technique I guess an approach that I learned at Facebook kind of to sum it up is the idea that you build a feature then you release it for just a few people maybe just people on your team you collect the bug reports and then fix those then release it for more people maybe just employees and fix the bugs they report and then release it for more people and you go through this cycle so gradually you roll it out fix the bugs and eventually it's rolled out for everyone this was the approach that the react core team used to release react fiber and I was inspired to use a similar approach when experimenting with concurrent mode now at Facebook I was experimenting on Facebook products Facebook internal tools but for the sake of this talk I've translated everything to apply to it kind of this to-do app so the examples are very generalized should translate to the sort of thing that anyone would build so let's imagine that this to-do app you know our code and we want to migrate it to concurrent moon and for context let's also assume that it's legacy code you know how legacy code is maybe it's not always written in the ideal way and for example in this app we can be aware that the to-do items and the text input are using react but the header and the footer are not rendered with react you might ask me flarn 'hey why is the whole app not rendered with react well a legacy code sometimes it's just built a certain way and it can be hard to change B there are like plenty of valid reasons that people mix different approaches could be that so the header and the footer are using server-side rendering maybe the team has not adopted react server-side rendering that's fine so knowing all of this let's take the first step so we can enable concurrent mode with this app maybe just for the people in this room and test it out so take that first step we would wrap the route render call with react unstable create route so this will render the whole app in concurrent mode this is available today if you'd like to try it out yourself and then the next step let's load the app try it out see what bugs that we find hmm so just loading the page we see a problem the to-do items and the input are appearing after the header and the footer the desired behavior is that everything appears at the same time that's how it worked before we enable two concurrent mode so what's going on so if we dig in and look at some performance timelines we'll see that before we enabled concurrent mode this was how the code ran first we call react Dom render and then there's a JavaScript call to insert the header and the footer into the dump these all run synchronously in one frame at the end of the frame the browser paints and we see all the content appear now that we've naively enabled concurrent mode things happen differently we still call react Dom render but under the hood this puts the rendering work into a scheduling queue and then it lets the browser do any work that the browser has to do so that for example if you click or scroll that would be handled but in this case the next browser work that's up to be done is that call to show the header in the footer so that runs right away then the frame ends the browser paints and we see the header and footer appear early in the next frame because the browser is free the scheduler can run the work that has been scheduled and the react items appear but it's too late we have what's called tearing where things are popping in at different times so how do we fix this what we need is to be able to also schedule that work to show that Java Script header we need to be able to tell the scheduler hey this work should actually happen after the react rendering work so let's say we had a way to get access to that scheduler that react is using under the hood so then instead of actually running the function to insert the header in the footer we could give it to the scheduler then when the scheduler starts running its work it would run the rendering code and then insert the header in the footer everything appears at once so what might this look like in code so this is a very rough draft of what it might look like based on experiments that are ongoing there is no final API for this but just to explain at the top you see the original implementation and it just calls that function to insert the header in the footer so what we need to do is instead give that function to the scheduler maybe we would call a function called scheduled callback and that puts it into the same scheduling queue that the react work is in just to zoom in again this is not a real API but it gives you an idea of what it might look like cool so now that we've fixed this bug the app actually seems to be working well let's roll it out to some more people and see what bugs they report our next bug report comes in and people notice that sometimes and when when you're typing the input feels laggy and what we find is that there is a random set timeout callback that happens to fire occasionally during when someone is typing so you can see here if this set timeout callback fires and reacts is trying to update that input react again will yield the main thread and the set timeout callback runs now in this case we do not want the set timeout callback to interrupt react because updating a text input is higher priority than whatever that set timeout call Beck was maybe it was sending data to the server maybe it was handling some data that came back whatever it is probably should not interrupt the user typing so how do we fix this we would take a similar approach once again we need to schedule the work that's happening outside of react with the work that's happening in react we need to coordinate between these things so instead of giving some work to set timeout we would give set timeout a callback that schedules the work and we can specify that this callback should be lower priority than text input updates like typing or any other high priority update so now let's say we've coordinated all the work it's happening in our app the work that's happening in react and any other JavaScript that's running so again things seem to be running smoothly so let's roll it out to some more people and see what bug reports we get maybe employ all of our employees can try it out so this bug report only happens once in a while it's kind of sporadic but it happens that people try to create but to do and they end up with too and in fact we're getting in maybe a dozen other bug reports but they're all kind of sporadic they don't happen every time I know you've probably had this experience before where you get a bug report and you're like okay I'm ready to debug and you open up your development environment take the steps to reproduce the bug and it doesn't happen and it's very frustrating you can't use git bisect to find it you you may have trouble fixing it it's you know hard if you can't reproduce a button to figure out what's going on at this point in the real story and begin to feel like the app was haunted write it like there just like that right that's like a poltergeist just moving things around when I wasn't looking so luckily I can explain for all of you the root cause of this issue and and then it won't be as mysterious for you so going back to the duplicate to do bug the problem was that the call to save the new to-do item was being made in the component will mount of the new to-do item you can imagine someone might have had the saw it oh when we add this to do to the list I'll just save it to the server now even when you're not in concurrent mode this is an anti-pattern we should not rely on when react mounts or unmount components that's an implementation detail it's not a good place to put something like an API call but in concurrent mode this really can cause problems even more so because the component will mount method could be called twice in certain circumstances now to explain we have to understand more about how react renders so when react renders there are two parts the first part we call the render phase and this is one react is updating the virtual dump and various life cycle methods are called during the render phase the second part is what we call the commit phase it's very short and this is one react updates the actual Dom notes and this is when component did merit component did update component will mount get call so the first part the render phase this is when react might yield the main thread and there could be an interruption if there's an interruption react may have to stop and then start and may even restart depending on circumstances so that can lead to some of those life cycle methods being called twice if they react comes back and has to restart some work so any life cycle methods listed under the render phase are not safe places to put an API call or any other side effects you should put them in the commit phase life cycles which will only be called once so you might think okay I'll just move all side effects to the commit phase life cycles and that's good the problem is what we found with tons and tons of reactive components and teams using react at Facebook is that this anti pattern of putting side effects in these render phase life cycles was very widespread there's a really big gotcha and as I mentioned it can cause bugs even when you're not using concurrent mark so the react team made this improvement to the react API by beginning the process to deprecated some of those render phase lifecycle methods and replacing them with get derived state from props and get snapshot before update the names of these two new methods are very specific and they should be a clue that it's not a good place to do something like save you know make an API call or save something in any side-effects so let's say we remove all the deprecated lifecycle methods from our to-do app we should be good right well I hate to break it to you but it's still possible to run into these anti patterns even if you remove all the deprecated lifecycle methods from your app this is an example I actually have seen when people are migrating away from the deprecated lifecycle methods they they move code from component will mount into the constructor and the problem is the constructor may also be called twice in this example the code removing creates a subscription to a backbone collection so if we move it to the constructor and the constructor gets called twice it would create two subscriptions we normally clean up subscriptions in the component will unmount which would only be fired once so it would clean up one of the subscriptions the other one would never be cleaned up this can cause a memory leak the real solution in this example is to either move the code to component did mount which will only be called once or to make the call I don't potent meaning it will only create one subscription no matter how many times it's called so with this understanding let's say we remove all the side effects from the render face for real so now again we've we've squashed those sporadic bug reports that were coming in let's try rolling out our to-do app to our production users and see if any other problems get reported so there's one more problem that comes in and I'm gonna use a really simplified example to explain this one I call it the mutable store problem and I find it fascinating so hopefully this makes sense for all of you to start like I said this is a more simplified example it's a demo I wrote where the circles and boxes are a react component tree each circle is a component that reads its color directly from the color store which is just an object we can see in the top right and the buttons at the top will either re-render the react tree or change the color in the color store so when things are working correctly we would probably first change the color toggle it to orange and then we re render our react tree I slowed down the render just to make this easy to follow and they all read the color orange so I wonder what would happen if we click these buttons out of order or in various orders so let's let's see so if we begin a rerender and then change the color in the middle then reacts actually ends up committing a tree that's an in an inconsistent state so to explain what happened here and this is real code this can really happen react began rendering and calling the render message for each of those components and called the render method on the first circle and the second circle and they read the color blue from the store then when we clicked change color react actually yielded so that the browser could handle that click it's just a vanilla JavaScript click Handler and it changed the color in the store so after that react comes back and continues rendering these components so it's calling the render method on each component and when it gets to the third circle and calls the render method that circle reads the color orange from the store now this might seem like a corner case but again it really does happen and in the worst case it could throw an error let's say I click a button and deleted the store completely then when those components try to read from it they would throw a saying cannot read color of undefined so how do we fix this I'm gonna kind of summarize the fix that there's at least two potential things I think that ideally react would handle this situation gracefully under the hood so at the time that we ran into this the team added some code that basically would would catch any error thrown in this situation and restart the render synchronously from the root component so that would force the tree to be in a consistent state if the error is not thrown again then it gets ignored basically but I would not rely on this that's an implementation detail and you again you could still have problems if an error is not thrown but you may you know you may still have an inconsistent state went there with the tree I would say that the real solution is to use references to an immutable store such that if we change the color it would create a new copy of the store and the components would still have a reference to the old store and to get the color change to propagate you would re-render the from the root using a reference to the new store cool so let's say we fixed that bug and now our app is actually running smoothly for all users congratulations we've migrated our app into concurrent mode and released it but I have to admit there were some hiccups along the way so what does this mean we did not end up fixing any bugs in react really all of the problems that we ran into had to do with the way that we write our JavaScript code so I would say that using concurrent mode is a different paradigm from the way that we've written JavaScript apps in the past I think of it as being similar to a multi-threaded model so the key idea if you remember one thing from this talk is that in concurrent mode different pieces of work can be scheduled in a variety of ways rather than always happening in the same order I also point out that as you saw for each problem we ran into even with this legacy app there were solutions so so that's encouraging I think and lucky for all of you many of these solutions are wrapped up in react strict mode so raise your hand if you've heard of or try and react strict mode oh I don't see any hands we should all go home and like try react strict mode the benefits are you know super important if you want to try out concurrent mode it warns you for those deprecated lifecycle methods and in development react strict mode will always double invoke the lifecycle methods which could be called twice so that means those ghostly sporadic bugs we saw they will always reproduce consistently if you use react strict mode in development even if you're not using concurrent mode there are other helpful tips and warnings that get added in strict mode so highly encouraged trying it out I also you know think that when you are using concurrent mode have some other tips so here's kind of a cheat sheet I would start by using react strict mode and fix any problems that it flags I would then coordinate all the work that's happening on the page not just the work in react I would avoid putting any side-effects in the render phase lifecycle methods them to the commit phase and I would also keep in mind that this is very new technology and just experiment try things out share what you discover and I have a bonus tip I would highly recommend trying hooks and suspense with react concurrent mode now you should still try them even if you're not using concurrent mode they're great by themselves but they also were developed with concurrent modes so they should work very naturally together with hooks you don't have to worry as much I think about which lifecycle methods you're using you're just using hooks and with suspense I predict that suspense may use or coordinate with concurrent mode for some of its features so I recommend trying those together and I would also encourage people to just experiment with JavaScript scheduling in general this is the next big problem that we get to solve as web developers and framework developers and the solution may not come from react it may come from new browser api's or other frameworks so let's explore this new space it's an exciting problem to solve so in conclusion I'd say that scheduling javascript is a paradigm evolution compared to the way that we've written JavaScript apps in the past it has powerful potential use it with an understanding of the constraints that it imposes so I'd like to thank a bunch of people thanks to Czech engineering for supporting me as you mentioned we're hiring again thanks to the react courts even web core team the people I worked with during these experiments toda thanks to react next and thanks to all of you thanks for joining me on this adventure [Applause]
Info
Channel: ReactNext
Views: 12,902
Rating: 4.915916 out of 5
Keywords: react.js, react, reactjs, react next, reactnext, Flarnie Marchan, Concurrent Mode
Id: V1Ly-8Z1wQA
Channel Id: undefined
Length: 25min 41sec (1541 seconds)
Published: Thu Jul 04 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.