Beyond React 16 by Dan Abramov - JSConf Iceland ⚛

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Applause] so Dan is a developer who loves empowering other developers by building tools he works in at Facebook working on react he has a few open source projects out there that you might use like myself we I like working on reacted Redux and all these things that you know help us try to be better and more productive developers also right before the event he tweeted this almost a little click Beatty tweet I'm gonna read it you don't mind using a strange new API I have never felt this productive using react before you're going to hate it then you're going to love it will spill some beans in a week at GFI yes now here we are let's hear it from dead [Applause] all right hi my name is Dan and I work at Facebook on the react team and in this talk I want to talk about the future of react and originally when I planned this talk I thought that I would talk about react 16 release and then the upcoming react 16 free release which finally fixes the contacts API and then talk a little bit at the end about the future of react but I was playing with some features that my teammates have been building like future features some of them we've talked before some of them we've never even talked before and I realize that I actually want to dedicate my whole talk to these new features that aren't available yet but I find them pretty fascinating and I hope you like them too so disclaimer I'm going to show the demos this is a very kind of demo oriented talk the things that I'm showing are not production already yet the exact api's will change don't fixate on them too much but I want to emphasize that this this isn't real builds of react so there's enough fake journalists these are using actual actual react code and I want to start with the question and the question is as library developers we need to think about our immediate users the developers who are building apps and also the users of our users that is the actual people who is in those apps and so at Facebook our scale is pretty global so we need to consider all kinds of connections and all kinds of devices such as your high powered CPUs like on a laptop or low powered CPU such as on the mobile device and either fast or slow connections and we need to think about how can we as library developers empower the application developers to give the best user experience regardless of the device or the network and is there anything that we are can do better to enable them so when we think about those issues we tend to group them into two different areas the issues related to the computing power and the differences in the computing power and the different the issues are related to the differences in network speed and I'm going to refer to this as CPU and IO and in the context of react when we think of the CPU work you usually think about creating the Dom nodes creating components rendering them updating them calculating the updates and so on so the things that are tend to be synchronous and when we think about the i/o work in the context of react we should think about the data fashion and the code splittin so is there something that reacted to better in those areas I'm going to start with the CPU area and I have a demo as I said this is a demo oriented talk so this is my demo it may be it doesn't look like a real app that you build but at least it's pretty beautiful and it's graphic so it's easier to see from the audience but what I have here is I have a tax box I can type into the text box hello comma and I have a bunch of charts and every time I type the charts update and I made it so that the longer I type the more complicated the charts become so this lets me show that no matter how fast the implementation of component is eventually if the component tree is deep enough and there are enough Dom nodes there is enough computation is going to slow down and I don't mean turn it because on a specific like chart example the you can imagine that instead of a chart there could be any kind of react component tree so the main point is just that it's a heavy tree with a lot of dumb notes a lot of components and it updates every time I type and so already with this level of complexity when I type I experienced and I'm the one who experiences it you're probably maybe you don't see it so I build a small clock so the clock shows the how how the screen updates so when the when the crate sorry when the clock is green it means that the last frames are were drawn pretty near to each other so it feels responsive but if you see when I type I can see yellow and even red this means that it takes a lot of time between different frames so the user experience suffers and eventually no matter usually no matter what kind of app you're building eventually you're bumping into this problem where no particular component is slow but you just have so many features and such deepness then that you have this problem so the typical solution to this is to debounce the input so instead of updating the updating the output immediately as a type I can just wait until the type and finishes and then to a single update so I can type the the input is completely responsive but then the user experience suffers in the sense that if my computer is actually powerful enough so like I will remove some characters to make the the the complexity smaller I still have to wait until to finish typing to see the results so this program doesn't really adapt to the performance of the of my computer and to the complexity of the team and this is even more pronounced if I enable the CPU throttling so CPU throttling is a way to emulate performance of a mobile device of a less powered device so I will slow down the CPU by 4 times and now you can see that even so a type J is called Iceland and even though you waited a little bit it still froze the underlying problem is just that the update is big and it's synchronous so as soon as the react starts rendering it cannot stop well what if there was a way to make updates asynchronous so that we actually start rendering something but then healed back to the browser and if there is a higher priority event like an input the browser could handle that first and not started a thread so I will disable the throttle thing for now let's see how it normally behaves in asynchronous mode so what you can see here is that when the input is short and it doesn't there is not a lot of computation you know there's almost synchronous it so it feels like as if it was synchronous but if I type more what happens is that instead of hanging the thread the thread says responds if you can see that it's most agreeing but instead react just updates the chart it's left less often and they lag behind my input a little bit but in many cases this actually doesn't matter and it's a completely fine compromise from the UI perspective let's see what happens on a slow device so I enable the CPU throttling four times slower you can see that it does starter a little bit but it's mostly green and it tries to catch up to my type in even though the device is slower compared to the synchronous version where it just stutters on every keystroke of course in real apps you often can optimize updates specifically so maybe only part of your app updates and so you can just update those components and avoid a large update but not every there are also scenarios where you just need to mount and you have a tree so I will unmount this chart completely and then mount it again with throttle enabled so that's simulating a slow device and you can see that it hangs every time and while it's while it's rendering the chart nothing is interactive so I can actually click on this clock to simulate an interaction but while it's mounting it doesn't register my clicks now debouncing doesn't help us here because d bouncing is only helpful for updates but here I'm just mounting a huge component tree so let's compare this with asynchronous mode and I still have the throttle and they enabled so that's emulating the slow device so in asynchronous mode you can see that even though it stutters a little bit it doesn't go into red and interestingly the circle stays interactive so I can actually I can start mountain I can click on this interact with this so the whole app is still working while the rendering is mountain in fact I can even start typing in the input and it's going to update to my type in so that was the CPU demo [Applause] and I want to emphasize that this is not about the charts or the inputs we've built a generic way to ensure the high priority updates don't get blocked by low prior to update and in this particular example high priority update was updating the input and a low priority update was rerender in the chart but it could have been any kind of react component for example a feed story that gets loaded and we don't want to freeze the scroll while we'll load in new items in the feed and we call this feature time slicing so it doesn't block the fraud the threat while it's rendering and if my device is fast enough it feels almost like it's synchronous but if it is slow then it feels at least it feels responsive so it adapts to the device thanks to browser exposing a request idle pull back API that we use for that also notice that only the final state was displayed the update the render screen is always consistent we don't get artifacts of slowly rendering something that is going to cause the tranquille user experience we only flush when the low priority update is ready and you might think oh maybe I changed those chars to like make it's probably a lot of work to make charts this chart component work like this but actually I just used it a ready-made component from NPM I didn't make any changes to it so we can look at the code and it's just to run a regular render method I have a chart component the it renders components from NPM I pass data to it and I call set state and I use a special flag to tell react that it's it's a low priority sad state and personally I found it very helpful to use version control as a metaphor for this so when I didn't know about version control and I would just modify the files as I've worked on them hopefully I never like did anything silly that I can't undo so I would just work on the feature in my application but then if suddenly in the middle of working on that feature I need to fix a bug now I can do it because I only have one version of my tree so I have to finish working on the feature first and this is kind of how react works without time slicing the react that you know is that it can't interrupt the lunk update but when I learned version control I learned to work on a branch so I could start working on the feature working it in the branch but then if I need to do an urgent bug fix I just do it and master and then I can rebase the branch on top of that and so this is pretty much how react works with time slicing except that you don't have to rebase anything and react does that work so reactor term is how to apply a low-priority update on the top and it can continue working and then flush when everything is ready just like I can merge the branch when it's ready so we'll look at what we have could do better at the CPU side what about the i/o data fetching and code splitting I have another demo that's that's the fun part [Applause] all right I built a movie app so you can see this is the app it has a list of movies I can click on a movie it shows the detailed page were with movie details and the reviews and that's basically pretty much everything that it does so it has an app component at the top that renders either movie list come movie list page which is this page or the movie details page which is this page so there is just to kind of pages here and the data is currently absolutely hard-coded so there's like a JSON with with the array of those things and we take the data by ID from the JSON so what if I wanted to change that to fetch data from a remote API let's go to the movie page component I'm going to remove the hard-coded movie details trace and import and instead I will import fetch movie details from API all right and I'm going to use another function that I'll import from the future again the exact API doesn't matter it may change most likely so I will call it create fetcher for now then I'll go to the movie details component so currently movie details reads from JSON object but I'm going to do something different I will create something called a fetcher so I'll call it movie details fetcher equals create fetcher and I will pass my promised return the function fetch movie details through it now the next step is going to be a little bit controversial so if you know react you probably know that you're not supposed to do data fetch and inventor so in this talk I'm going to ban this rule a little bit and I just want you to follow along with it and see where it leads us so when react came out he was pretty controversial and I think we can make more controversial things all right so I have this virtual object and it works as a cache it has a single method called read so I'm going to call movie details fetcher that read and pass the ID so what's going to happen is that when a react renders the movie details component it will try to get this data from the cache but the TV is not there because it's not fetched yet so reactor is going to fetch the data and Rehab is going to prevent the entire update from occurring until the data is ready there is just one more thing I need to do I need to tell react that is actually okay for the transition from this page to the details page to be asynchronous so again the exact API is probably going to be different but here in the movie click where it says state show detail true I will call something called differs at state with the same state so let's see if that works I click on an item it waits and it loads and if you don't believe me I actually built a small debugger here so it shows the pending requests and how requests happen so if I remove everything from the cache and I click on the movie there is a request here and when it comes back reactive renders the detail view now you might think oh there must be a race conditions and maybe you think that this screen is not interactive well as fashion no it's it's interactive I can click here I can click here it's going to load the right one now it's in cache I can go back I can click on this movie it's in cache so it renders instantly however what if the latency is high what if the network request takes a lot of time like in this example three seconds but it could have been like 15 seconds so now if I click on a movie it seems like nothing is happening if you don't have the debugger open so that's not a very good user but we can improve it so I'm going to import something else from the future it's very convenient to have access to the feature I'm going to import a component called a placeholder and I'm going to say that if anything inside the movie page is not ready we're gonna render a placeholder if the movie page takes more than a second and a half to load so there's a delay of a second argument then I want to show a spinner so what we are is going to do is going to try to render this component but if any of its child is going to render as much of the tree as it can but if any of the children are waiting for async dependencies is going to wait for those children and if it takes more than this amount of time is going to display the fall the placeholder until those dependencies are resolved so let's see how this works I'll click on the movie in this case my default latency is 1 second so it actually feels almost instantaneous so I don't see the loading indicator but if the latency is high 3 seconds and I click on a movie then it shows if the placeholder and then it shows the real thing when it's ready here's another interesting thing even while it's showing the placeholder the app is fully interactive it's never frozen so I can pause all new requests start a fashion imitate the fetch it takes a long time but say I want to go back I can actually go back so the whole the screen is always interactive now which is fetched the details but what if we want to fetch the reviews as well to do that I'm going to back to movie page component and I'm opening the let me import remove the hard-coded chase on import and instead import fetch movie reviews and I'm scrolling down to my movie reviews component that currently reads it from Jason and I create movie reviews fetcher great fetcher with fetch movie reviews and again I just call read I said sorry movie reviews fetcher dot read for props idea so movie reviews and movie details are siblings but reactor is going to wait for both of them before continuing so let's see if the latency is one second is waiting for both but both resolved in time so it doesn't display any intermediate loading states and doesn't the page doesn't jump with spinners but let's say that I pause near requests I start fetching I'll let the reviews come through first while the reactor can't render reviews alone it's important that the screen is always consistent with what's in the render methods so we actually still showing the placeholder but when the details of the movie are loaded this is when it shows everything together now this may be fine but there is a downside what if I actually don't care about the reviews that much and I don't want to delay showing the details if the details folded first well to do that I use the placeholder component from the future so I can wrap the movie reviews component in a placeholder and I can say that if the movie review specifically took longer than a second to load since the interaction we actually don't care about them that much and we're going to show another spinner with a medium sized let's see what happens so our puzzle new requests start loading a movie and allow the details first it shows the details but the reviews are still loading and when the Reeve is already it shows the reviews and again there are no risk conditions I can go back I can clear this I can start fetching this start fetching the reviews go back well here start afresh in the details it knows exactly what's the right thing to do and it respects the props that I pass through it but we can still make the user experience better for example when I just click if the delay is less than a second it's nice that the screen pops in is ready but before that happens I don't have any visual indication that something's happening so can we fix that yes I will go into the app component and I will import something else from the future it's called loading so this is not the final API this actually this API is most likely to change but for now loading is just a component that gives me a render prop called is loading that lets me decide what to show for now I'll copy paste what I already have here so either the detail view or the ListView but I already prepared my movie list page in a way that I can pass a load and ID to it and it will show an inline spinner so for example if I pass loading ID equals 1 it shows a spinner like this if a password and D equals 2 it shows a spinner on the second movie so what I'm going to do is I'm going to make loading ID and argument to render list and I'm going to call render list so if we are currently loading which is what we wanted to ask react then I just pass the current idea otherwise I pass null and I can even remove the the main placeholder now let's see what happens so now when I click it shows an inline spinner and again no race conditions I can click here then click here it shows the right thing the screen is always interactive and now this is cached so this is all cool but we can still improve the user experience even further for example currently we show the the movie page below the code for the movie page right away but we don't actually need it until we click on the movie so I'm going to replace this with a component that does code splitting so I'll call it movie page loader and I define it above it takes the props and passes them to movie page so if we are code splitting do we need to show a spinner while little how does a question even make sense if we have these new primitives that's same I'm going to import create fetcher again and I will create a movie page fetcher to patch the movie page I will use the dynamic import syntax so I will return a promise that returns import to movie page and I remove this static webpack import so it's not going to be in the initial bundle finally to get the movie page component I call the read function on the fetcher and read the default default property from the module because it's the default export I'll see if that works I click here there is no global loading indicator if the request takes fast enough yeah just edit code split into my app but if the request is slow oh I guess I removed the fallback so yeah that's not going to work but we can check that this actually did something so if i refresh I clear the network top and I press you can see that there is a chunk here so you can see that this component truly was loaded with collision there is still one improvement to the user interface that I can make her you might have noticed that this movie has a taller poster than other movies let's say that we don't know their sizes immediately so when I click on it for the first time the page jumps a little bit when they when the movie loads so can we avoid showing the page until the image is ready well we can go to the movie page component and find the movie poster component that renders an image and I will create my custom image component with capital I the choice render is the browser image except with the twist I create an image fetcher which is a fetcher now I need to return a promise so return a function that returns a promise that resolves when I create a browser image object to preload the image and what that image loads I resolve my promise and I started the loading process and now I say that the source is image patcher that read prop source I'm bad at this right yeah this should be an argument because I pass it to the wreath so it's going to come out here now if I click on it that didn't work okay it's a live demo some things that's why you should let look at the lint warnings so let's use the image component now I'll click on it and jumps on the page when the image is ready and this was the i/o demo [Applause] we built a generic way for components to suspend rendering when they load asynchronous data or dependencies or really anything asynchronous and we call this feature suspense you can pause any state update until the data is ready as specified by the components and you can add agent load into any component anywhere deep in the tree without clumping all the props and state and hoisting it up and using readouts or anything you usually do for that and on a fast Network the upside is that you can make it appear very fluent and almost instantaneous without the cheran cascade of spinners that appear and disappear all the time but on a slow Network you you can be intentional about designing the loading States and not just let them be artifacts of how the code is written in study explicitly design which load and States you want the user to see and how grenier of course they must be and there is both a high level and a low level API so the API that I showed you is a high level reference implementation that we're going to provide but there is a lower level API that libraries can use to integrate with this and again I found it helpful to use version control as a metaphor so when I use version version control and I start working on something and do this on a branch but sometimes maybe I can't continue working on the feature because I'm waiting for the designer to give me the final design so I put that work aside and I can do something else and this is how I react suspends works is that react knows that these some of the children need some async dependencies so it just suspends that tree but it can still handle a higher priority event so this is why I was able to click on everything and continue navigating through the app and later just like I can rebase my old branch when I finally have the designs on top of the master react rebuses the suspended update and can continue when the async depend satisfied and then committed to the Dom so coming back to my question how does how can the reaction able better user experiences for people with different devices and different networks within that time slicin helps the CPU case and the the saucepans feature helps the i/o case is that we can be more intentional about designing for slower devices and how they should behave but we can also provide better experiences of past devices and you can see that there are a lot of similarities between these two these two axes so this is why we don't really think these are separate performance problems we think that both the problem the main problem here is not the performance but scheduling and the solution has to think about the scheduling and so we call this see the features agent for entering in react and our goals is to let app developers adapt to users constraints such as device and network to make fast interactions feel instant without the janky things popping out of the screen and make slower interactions feel responsive and we designed intentionally and importantly this is still the react you know this is still the component declarative component paradigm there if he is reactive you probably that's what you like about it so it's not ready yet but these are not fake product like you saw me really using it so it's a real thing there is a pull request for this and there is more work to be done to enable this and to ship this as a stable feature and we hope to deliver it this year thank you [Applause]
Info
Channel: Baptiste Adrien
Views: 65,452
Rating: undefined out of 5
Keywords: react, js
Id: v6iR3Zk4oDY
Channel Id: undefined
Length: 34min 22sec (2062 seconds)
Published: Thu Mar 01 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.