Performance - Lecture 11 - CS50's Mobile App Development with React Native 2018
Skills:
Frontend Performance80%
Key Takeaways
Discusses performance optimization in React Native, covering topics like trade-offs, measuring performance, and common inefficiencies
Full Transcript
[Music] hello and welcome back for lecture 11 this week we'll be talking about performance so in the previous lecture we talked about a few different things we forged ahead with our simple Redux I mean that one we did an asynchronous action we then saw that it might not be good to change our implementation of Redux in order to do that and so we found out what Redux Middleware was and by using Redux middleware we were able to add asynchronous actions to redux itself then we talked about another Redux add-on called Redux persist which allows us to store our state into whatever storage mechanism we want and then rehydrate our app based on that information we then talked about what the difference was between container and presentational components so if you remember container components are the ones that are hooked up to your Redux state and then they passed down props to what are considered presentational components and so presentational components are only they only care about the props that they need to display themselves we then talked about it to a couple different tools that we can use for writing JavaScript those being es lint which allows us to enforce some style rules and Peter which allows us to rewrite our automatically rewrite our files such that they abide by these rules so this week we'll be talking about performance and so what exactly is performance performance is how quickly or how efficiently something works and if we want to make that better we can do what's called performance optimization and by doing that we can make something work as efficiently as possible performance optimization is actually a very very wide field but today we'll only be talking about optimizing the JavaScript side of things I will mostly be talking about high-level things with a few examples along the way so one thing that's important about performance is knowing that they're actually trade-offs involved so by optimizing performance we we usually pay some sort of cost and this cost is usually in your applications complexity so in most cases is actually not worth optimizing your code javascript now is so fast that by optimizing you add complexity to your app and sometimes that complexity and maintainability is really not worth the little to no games that you'll get from optimizing and so in general you don't want to over optimize anything until you found a bottleneck and by bottleneck I mean something that's slow enough that it act that one particular thing slows down your entire app and so how do we actually measure for these things called bottlenecks well there's a few things actually built in first we need to remember what environment are we running our application in and so there are actually two different environments built into node or our bundler one is production and one is non production or what we what most people consider development mode and so the way that we actually set this is in the xte if you click this gear icon here there's drop-down where you can change host and you can also toggle this thing called development mode and so by checking this and unchecking it I can actually determine whether or not my application is running in development or production mode important to note if I change this I should actually restart the bundler such that it actually is indeed running in the mode that I want it to be react actually has a few optimizations that it does when it's in production mode and so things like prop types aren't necessarily checked and warnings and errors are not necessarily displayed so there's a few tools built in to react native itself that allow us to benchmark our performance and so one is called the react native perf monitor or performance monitor well this does is it shows you the refresh rate of both your UI and your JavaScript thread so if you remember back to our lecture on react native we talked about how there was one thread for rendering the UI on the native side and one thread that's actually executing your JavaScript and so this react native perf monitor allows us to see the refresh rate on both these threads and so anything below 60 frames per second means we're actually dropping some frames and so there is potentially a bottleneck in whatever we're dealing with and so to show you how that works I'm running this simple application here what we can do is shake the device and it brings up this menu and we can click the show perf monitor and that shows this thing here which is draggable which shows us a few things one is how much ram were actually using so how much memory is your application consuming and of that memory how much is being consumed consumed by the JavaScript itself or the JavaScript core we then see how many views are in our application the top number refers to how many are currently in view and the bottom number is how many there are just total and then we see the two things that I mentioned the UI and JavaScript frames per second meters and so since they're both locked at 60 frames per second it means we're not dropping any frames or there's no bottleneck and what we're currently doing here and so what happens if we actually want to introduce a bottleneck and so if you remember back a few lectures we implemented this application where we just display a bunch of contacts in these contacts are generated by that contacts JS file that we talked about a few weeks ago and in this case I actually reverted back to our scroll view if you remember scroll view versus flat list or section list the flat list and section lists are virtualized lists which means they only render what's currently in view whereas the scroll view will actually render everything before displaying and so if we toggle it and then turn it back on we see that our JavaScript thread does indeed drop well below 60 frames per second so once again we can toggle this and then when we toggle it again it has to render all of these contacts I believe they're a thousand being shown and we see a dip in the frames per second in our JavaScript thread cool and so by using this perf monitor we can we can navigate through our app and find out exactly what screens are causing any frames dropped if we want more detail we can use what is called the chrome performance profiler and so I alluded to this a little bit last week where we can actually run our JavaScript on inside of Google Chrome and so we've done this a few times in the up in the past and what this does if it shows you a flame chart of all of your components and I'll show you what that means in just a second but one thing to note is that this is only available in development mode if you're running your application in production mode this option will not be available for you in so since we are indeed enveloped in development mode we can use this debugger and so what I did was shake my device bring up this remote debugger I clicked on it and it's now running my JavaScript inside of Google Chrome and so we talked about how the JavaScript is actually separate from the UI threads and the way they communicate is through this bridge and so it doesn't really matter where our JavaScript is running as long as it can communicate with our UI thread and so since it's running currently in Google Chrome I can inspect and see what's going on and so here you can see elements console sources network but the tab we're actually looking for right now is performance and so here we see a bunch of options we see we can click the record button or press command D to start a new recording we can click the reload button which will reload the frame and record the page load unfortunately this doesn't really work in react native it's more something that's geared towards web but we what we can do is we can press the record button do a few things in our application and then come back and see exactly what what has happened in our JavaScript until let's toggle the east of they're not visible let's start a new profiler recording go back toggle them you see that it took a while to render and then we can go ahead and stop this profile and then chrome will analyze things and show us this chart here and so we see frames interaction main raster GPU user timing and what we're looking here for here is user timing if we dive into user timing we can see a few things we see the react tree reconciliation we see contact screen update which is our contact screen that we have here we have a view scroll context go for you contact scroll view mount and then we see a bunch of things and if we zoom in all the way we can actually see that each one he is a row being melted and so this is what a flame chart looks like a flame chart is a chart that is basically our react tree but graphed out over time and so we can see these numbers up here which correspond to the time line since we can we click that record button and what is happening as these milliseconds tick by so you see 3,600 milliseconds 36 50 milliseconds and so in this 50 millisecond time span what has happened well we have been rendering our scrollview contacts we've been rendering our scroll view and within that 52nd millisecond thing we see that all of this happened and what exactly is there well we can zoom in and see that we've rendered a few rows and what happens at each row mount well there's a view in there there's some text there's another text and there's text context so we can see that for every single component that we have in our tree each one takes a little bit of time to render and we can see exactly what's being rendered by looking at this flame chart and so if we refer back to our code we can see that the app all it's doing I removed a lot of the stuff that we did last week since it's not necessary for this particular example I have my es lint thing popped up we can see that this app is only doing one thing it's rendering provider which as we remember from last week is what allows us to access the store our redux door anywhere in our app that's given to us by react redux we see a view which just has a few different styles and we have a contactless screen and so what is being rendered there the contacts the contacts list screen is just rendering our contacts list and what exactly is our contacts list well it's defined here to be the scrollview contacts and what is scrollview contacts we can see that it's just let me silence these errors real quick so I'm running pretty really quick just to silence those errors and then now I can view with without my yes lint integration popping up and so scrollview contacts is just a scroll view and what it's doing is it's taking our contacts which is an array that's passed down it's mapping over them and for each contact we're rendering a row and so we can actually see this exact structure of our app in that flame chart and so we saw our app we saw about its rendering something called the contacts list screen we saw that the contacts list screen is actually rendering the scrollview contacts and we see that the scrollview contacts is a scroll view with a number of rows that corresponds to the number of contacts and if we again refer to that flame chart we see a our tap which is the top level component we see our contacts list screen we then see that it has a view inside of it and inside that view we have our component called the scroll view contacts we see that that is actually refer rendering a scroll view and so if we just double check the code we can see that we have indeed a component called scroll view contacts which is indeed rendering something that is a scroll view and then inside of that scroll view we see a large number of rows and each row is referring to a row that is rendered right here and so this is just timing for us all of the components that we have in our tree and so it might be an efficient inefficient to render all 1,000 rows when we want to just mount that app and so what we want to do instead well we saw a few weeks ago that we can actually rather than using a scroll view we can use a virtualized list a list that only renders what's in view currently so let's go ahead and do that we have implemented from a few weeks ago that section lists contacts and in here we are actually using a section list which is indeed a virtualized list so again let me silence these errors so here disable this next line and here as well all right so this should shut up those errors and so we see here that we have our section list which does a little bit of logic in order to separate our array of contacts into the data structure that the section list is looking for and then it goes ahead and renders a section list and so this is code that we wrote a few lectures ago and we see that we pass it a render item which it will use to render the items as they appear on screen and so it's important to note that only what's currently in view is being rendered it's not rendering all thousand of these contacts before it's showing it on the screen and so let's go ahead and in our contacts list screen we can go ahead and flip this boolean here so that it's rendering the flat list contacts rather than the scroll view contacts I just did this so it's easy to do this quickly during lecture so I don't have to type so we can now see that this now renders almost instantaneously it's just because it's only rendering what's in view until let's now do this again make sure it's not in view start recording a profile render the view and then stop and now we can go ahead and see this flame chart to see if it's rendering as many contacts as the scroll view did and now we see something very different we see over here on our app inside it a virtualized list it turns out the virtualized list within it has a scroll view and let's see how many rows are being rendered so we see now we get to peek into the internals of how this section list is being rendered so we see that there's a view with a cell render inside that cell renders the row being called and inside that is a view so you inside the row is exactly what we have inside our own plantation it's a view with a couple pieces of text in it those texts are just the name and the phone number but we see that one two three four five six a lot fewer than a thousand of these are being rendered and the reason is because it's only rendering what's in view and so we can actually see proof of that by one just toggling the buttons seeing that it renders almost instant instantaneously but to actually just looking at this flame chart and seeing that within this scroll view here there's actually only like 15 maybe 20 rows that are being rendered rather than all 1,000 like the previous one and if we wanted to take a peek at the internals and see how this works we can see that this virtualized list or the our section that's not we're using is actually calling a virtualized list under the hood and that virtualized list is actually using a scroll view under the hood and so we get a peek at the internals of this component and so let's now stop remote debugging so we can forge ahead so now that we've seen how to actually look at the performance of our app let's start to actually optimize some things so what are some common inefficiencies in apps react native apps so one is just rerender and way too often another one is unnecessarily changing props and lastly unnecessary logic in Mount Update and so what does it mean to re-render too often well components actually automatically rerender whenever they receive new props we've been talking about this since nearly day one but sometimes a prop that isn't necessarily needed is passed and then if that changed it also requires the entire component to render and sometimes that's completely unnecessary and so how do we actually go about fixing that well if we're using something like Redux we only need to subscribe to the part of the state that we actually care about and so in our map state the props function no need to subscribe to some props that aren't necessary for the app so that was a pretty easy optimization another thing is using peas and arrays or lists and so in P and a few lectures ago we talked about why that's necessary and if you remember back to then the way that react works is that every single time a component is rearend 'red it will actually diff something in the virtual react tree with what's actually rendered to the app and so if we have something like a list of maybe names and maybe the first one is jordyn and the second one's david and say we wanted to add a new person if we wanted to add somebody like you one and we wanted to add it to the third place in the list it's pretty easy for react to do it says okay we need to add something to our virtual little list and say this is what's currently on screen or this is what's currently on screen and this is what it's doing in memory so we can say okay we're gonna add your wand to the list here and so let's do this in red and then it can go ahead and do a diff which what's actually there it says oh this remains the same we don't need to change it this remains the same don't need to change it oh yeah one doesn't exist in the actual tree so let's add him here easy all we had to do is add one person at the bottom but what happens when we don't want to add the person to the bottom so let's retrace our steps a little bit saying the goal was actually to add you on to the top of the list then what needs to happen well if we act was just to do its thing and if it would say okay let's add you one here and now we have this new list so what's different between the first people in the list well they're different so let's change this how about the second person in the list well Jordan is different than David so we need to change that and then who's third well nobody's there so let's just oops this should be Jordan and then nobody's in the third list here so let's just add David so what ends up happening in this case is we changed all three things when he really only needed to change one and so by adding keys to a list react can actually keep track of what was in the new list that was originally in the list even if the order has changed and so if we let's just redraw this I find out all this we had Jordan David here and then we want to add you one to the beginning what happens in this case if we were to mark them and say maybe Jordan's ID is just the number one and maybe David's ID is the number two and maybe yo Juan's ID is the number three and so now we've marked them with what are effectively IDs so what happens now reiax says oh we need to add you'll want to the beginning of the list and now let's diff what is in the new list in the memory with what we actually have here oh yo 1 3 doesn't match Jordan but this here actually has a number 1 and we see that the number 1 is here oh we also see that David is still here so we don't actually have to change these we know that what we used to be part of the items that used to be in the list are still in the new list they just changed their orders so we can actually just move those two components down the list and add one new person here so react is smart enough to know hey these particular people didn't change they just shifted places in the list and so in the new list now that we don't have to recreate them we can just shuffle them around reuse them and add only what's needed to be added and the only way that we can allow react to have that optimization is by marking people with these IDs and these IDs must actually be unique otherwise it won't no say we had some third person here in the list with an ID of number one when it sees Jordan one here it won't know which one it should be and so it'll actually throw a warning Oh key error we have multiple of the same keys and so the constraint on this is that we must have unique keys but by doing by assigning keys to each member in a list reacting have this optimization and lastly we have should component update which we talked about in the previous weeks when we talked about react lifecycle methods should a component update is a life cycle method that allows us to either return turn true or return false if we return true we're answering the question should the component update with yes and it will go ahead and rerender if we return false then we're answering the question should the component update with no and we'll actually snot rerender and then we see this new thing called a react pure component which we have never talked about so far so we've talked about a react component many times what is the react component well it's just the basic building block of react and what does it give us it gives us things like state it gives us those life cycle methods but it turns out there's another thing called a react pure component when it differs here is that a pure component has a predefined should component update where it just does a shallow diff of prompts meaning it looks at the props that it used to have it looks at the props and the new props that are coming down and we'll compare each one and does this at a shallow level and I think we talked about a shallow merge back in lecture 1 but it just means it will look at each prop it will say does this prop triple equal this new pump and so if it's something like an object it won't actually dive into the keys of the objects it'll just see if the object references map match and same with something like a function or array or any other object type in JavaScript so let's go ahead and do something here so let's add something to our app that will actually change the first contact in our list so let's revert back to our scroll view just so that any performance hits are noticeable because it is rerender in a thousand rows at once so now you can see that it it takes a good second in order to render this full screen and so let's add something like some sort of button maybe here where when you click this button it just changes the first person in that app and presumably we won't need to re-render all 999 other people but we'll see how we can tell react explicitly hey don't rerender these and we're gonna use something like should component update so let's just do a quick quick review of what's actually happening here so we have our contact screen we can toggle the contacts which is just something in state that decides whether or not we should render this list this list is just a scroll view which maps over all the contacts that we pass it and renders a row here and what is a row well a row is just a very basic view with a couple text things within it and so let's first implement this change and so we're going to need some way to tell our app hey we're going to do something here and generally when we're talking about a Redux app when we want to tell our app to do something and by do something I mean change something in our state we want to do that by dispatching an action so let's first add an action for what we want to do so within our actions a yes which is where we define all of our action types and our action creators let's add a new action type for changing a for the first user so we just added action type and now we are going to add action creator which is just a function that returns in action and if you remember back to a couple lectures ago an action is just an object with a type and maybe payload key so let's export something called change first contact it doesn't take any arguments and it just returns an object with the type that is change first user let me change this to contact cool so we now have our action type and so when we dispatch this type we need some sort of thing that allow that is listening and will change our data and so we do that in the reducer and if you remember a reducer a reducer right now is just built up of two smaller reducers one handles the user part of the app and one handles our contacts and so since we're changing the contacts we should update our contact reducer which is up at the top here we have a contact reducer is passed some state which is initialized to our contacts in an action and if our accident type is update contact we had a contact and now we're gonna add something that says if our action type is change first heat contact then we should do something else and let me remember to import that from our actions and so what do we want to do here we want to change our first contact and do that in a way that is immutable because if you remember back to the lecture on Redux every time we change our state we want to do that immutably and so we need to figure out a way to extract the first contact in our contacts list change it somehow and then add it back in so how might we do that well let's use some shorthand here so just like there's shorthand to pull keys out of objects so say we have we want to get the action type we could do something like this which is basically declaring a new constant to the type key of the action object we can also do some pattern matching on arrays so we could do Const first contact and the rest of the contact is equal to that array called state so in other words if state or something like name Jordan phone some phone and there are no there are no other people in this array what would happen is first contact would match to Jordan to this object here and the rest is just an empty array and so we'd be left with first contact is this object up here and rest would be an empty array until this allows us to D structure an array and assign it to a couple values okay so now that we have the first contact out what we can do is the new contact is going to be an object because we're doing the seamy to believe we're creating a new object here we can take the name or we let's let's actually take all of the key value pairs of first contact and just clone them so if you remember what this dot dot dot notation is doing is is saying take all of the key value pairs in an array in an object called first contact and put them into this new object that we've just created here and so this effectively immutably makes a copy of first contact and now let's overwrite the name and say the name is just going to be my name so now we've immediately updated new contact so that it's a clone of the first contact but we're overriding the property called name and replacing it with my name and now let's return some new state and what is in the new state well the first contact is actually going to be in the new contact here and then the rest are just going to be whatever was there before and so a quick recap of what's going on here is the state comes down is whatever the state used to be we're matching on the type change first contact and then we're using the shorthand in order to grab the first contact in our list we're just assigning the rest into this variable that were just to hold them for now and then we're modifying new contact and we're doing that immutably and so we're creating a new option a new object by using this object literal notation we're copying over all the key value pairs of the first contact and then we're going to overwrite one of those and so we're overriding the name and we're changing to my name and then lastly we are returning a new contact with the rest and then we can make this a little bit safer so say there are actually no contacts maybe if there's no first contact just return the state so that just makes it a little bit safer in case there's nobody in the first contact cool so now we've added an action which notifies our reducer that were we want to change our first contact we've added that logic in the reducer to actually change the first contact and now we need to effectively fire that action often so how are we going to do that well let's go into our screen and open our contacts on the screen and so let's add a button here which fires that off and so let's import that action we called it change first contact from our Redux actions that's create a new button that says change first contact and then all we have to do on press is just change first contact right so now we go here and we click change first contact but nothing happens so what is going wrong here so let's just sanity check so we import change first contact from our Redux actions so let's go see what that does so change first action change first contact here is a function that takes no arguments and so when we click the button it's invoking this function with no arguments so that's all good and then it returns an object that has a type key that is equal to change force contact and so what is our bug here why is nothing happening when I'm clicking change for his contact well all that's actually happening is we're invoking and a function that returns an object but nowhere is that letting our Redux store know that it should be dispatching an action and so how do we bind that function that Action Creator to our dispatch function the answer to that question is by using reactive redux and so if we go open up our contact list screen we see that we've already imported that connect higher-order component hired a component from react redux we're already using it down here by mapping our state to our pops and now we just need to say also bind our action creators to our dispatch and which one do we want to bind well it's the one called change first contact and so that is now binding our action creator called change first contact to a prop that is passed down called change first contact which is a function and so here rather than invoking the action that we imported from our actions file which is really just a function that returns an object you ought to invoke this stop props dot change first contact because that's the one that's actually bound to our dispatch function and so if we save that and click this we see that it did change the first contact and we can do it again and it has changed the contact again but it doesn't really matter because we're changing the name from Jordan Hayashi than Jordan Hayashi and we see that it it takes a little bit of time so let's refresh our app real quick it takes a little bit of time to actually do that because it's changing this and then we rendering our entire list we can make that even more obvious if we up the number of contacts that are being displayed so let's just open up the contacts file change 1000 here to 5000 and now it's rendering as we speak and now it's taking quite a long time and if we click this we see it takes multiple seconds before it renders and why is that happening well when we click change first contact two what happens it goes off to our Redux store and updates the first contact and then pass it back down here and what happens it renders that first contact with the new name and then it renders the second contact with the exact same information and renders the third contact with the exact same information that hadn't changed from the last time and so it's actually going down and re rendering 5,000 people were really only one of them changed were extraneous leery rendering 4999 contacts and so let's try to optimize that so we know that we can use this thing called should component update in RIA or react pure component and it basically just says hey if our props don't change don't rerender me and so how are we going to do that what we want to do in the row because Rose the thing that's ultimately receiving the pops and right now Roe is just a stateless functional component it takes some props and returns an element so let's actually make it stateful and so by making it stateful it can remember are just old props and react accordingly so let's actually do class row extends react got peer component and so by using a peer component here it's the same thing as a component with one thing changed the should component update lifecycle method is already implemented for us and it's just as a shallow death of the prompts and so let's do that must have a render method I've returned this and so all we changed is we wrote let's silence this lint we wrote a what used to be a pure functional component and we changed it to a class component that extends react pure component and if you actually looked at the lynn tears there's a error here where props is not actually defined because in a stateless component what is props it's actually this stop props and so you can actually create a variable called props which is equal to this dot props so I can just do that rather than adding this in front of those other ones and we can actually use the shorthand here and do const props equals this or in other words this we expect to be an object we expect it to have a key called props and so let's create a new constant called props and assign it to the value of the key props and so now if we save this now each one of the rows is a pure component again is taking a few seconds to render but now for each row here these are pure components and so they're react components that have a should component update life cycle method defined and what is doing is it says alright when you pass me new props let me see what my current pops are and check to see if the new props are any different and if they're not I'm not gonna rerender and if they are I will so now let's click that change first contact button and see what happens it was pretty instant again let's refresh it's gonna take five or so seconds to render the entire list and we see that when we click this button this changes in much less than five seconds and what's happening here well it's it's seeing well one it's dispatching that action off to a redux door it's changing the first contact it's then passing those props back down to this component and then it's its rear end during this component and for each row is passing down those contacts and for the first one it sees hey my name is difference so let me rerender and then the next one it says all right is my name the same as it used to be yeah it is is my phone number the same as it used to be yes it is so now I don't need to rerender at all now I only need to just pass and so it does have to do 5,000 the quality checks for each one for each row but the simple equality check there is much faster than rewriting the component but what if we're passing props that we don't intend to press we're passing maybe much more than name and phone and so we can actually optimize this further by saying we know that the only thing that might change is the name is the name really in this can case so we can actually optimize this further so rather than doing a pure component let's just do a normal component and let's define our own should component update and should component update is passed the next props and we can check well we know since who I wrote the code I know that the only thing like it possibly changes the name so I can just check if the next props dot name is different than the current props not name I can return true else I can return false or in other words just return the value of this boolean expression here so instead of saying if this is true return true otherwise return false I can just say return next props dot name is not equal to this props dot prompts done name so if we now run this it again takes five or so seconds in order to render the first time but now when we want to change the first contact that's actually roughly twice as fast as the previous one because instead of doing five thousand checks where each check is checking every single prop it's only checking a single properties only checking name and so by defining a should component update we save our component from Roux rendering too often so what's next in our common inefficiencies well unnecessarily changing props and so what might actually happen here is we accidentally or maybe not accidentally unknowingly change a value that is passed your child and caused a rerender of the entire subtree and so if you remember the way that a react app is expressed is this just a tree of a bunch of nodes so we have our app and then maybe your app has a couple different components maybe this one has a few different components and maybe each of these has a few and so on and so every single time we pass down new props the entire subtree is updated or could be updated depending on how its implemented and say these two things are pure components pure components pure component so now what happens if we pass down props that haven't changed then the rear ending is stopped there so again if if app updates its state but the things that these two nodes rely on those props don't change since they're pure components they say okay I'm good I don't need to update but say we accidentally change one of those apps change one of those props and we put pass a new prop down to this then the pure component says oh I was updated or one of my props at least changed so now let me rerender everything below me and so if we accidentally pass a prop that shouldn't have changed but actually changes then we are at the risk of rear-ending an entire subtree when we don't necessarily need to and so this is something that we see all the time so say we have an object or an array or a function or anything that can be expressed as a literal say we have an object literal in our render method that means every single time this component is rendered a new object is created just because it's an object literal in that sense so this means we might be rendering something that we don't intend to and so let's take a look at an example that has the side effect so let's implement something called a peer button and we'll only use this for an example all it is is going to be a button that will change colors if it's props are changed so let's just import react from react let's import button from react native and that's export default a class called pure button which extends react the pure component which as we learned in the previous slide is just a component that will check to see if it's if it's props have been updated if so it will rerender and if not it actually won't and let's just render and return a button where it just retains all of its props and this actually do something additional so let's have our state default to a color of null and if the component updates so component did update let's set state and update that color to be something red and this also passed light color down here so in other words we have a button oh and excuse this yes lint error so we have a component here what we're calling a pure button and all it does is it has a state which initializes as a null color and so when it renders it's just gonna be a button it's gonna pass all of its props just straight through to a button but it's also going to say hey I have a special color that at first it's just no it doesn't have a color but if I ever update I'm gonna change myself to be red and so this component here is just gonna show us that it'll turn red if we accidentally update it so let's now create a new screen let's have a screen that let's just copy it from our contact list screen so the screen is not going to have much we can actually delete these things let's it's probably gonna be faster just to rewrite it so let's have a screen first we need to import react we're going to import a view from react native and that's render this view and since I'll be quick I'm just gonna put the style in line and what's what should we have happen when you click the peer button so let's first say the pure button is going to have some style that will align itself to be centered and on press what should we do let's have it count so we're going to need a count here so this class extends react component it's going to be initialized with the state that starts at zero so if you recognize this example it's the example that we gave on almost the first day of class when you're discussing react native let's have a render method which returns this and what's going to happen on press let's do this set state and do the previous state and then return the count plus 1 and then it close that view and in theory this should every time you click the button it should increment the count and maybe we should actually show the count so let's also import some text and display it and let's also remember to import our pure button and that should close those errors so cool we just implemented the app that we had on nearly day 1 and let's go ahead and render it so import that pure button screen from pure button screen and render it so now we have oh we forgot to give a title to our button so let's go ahead and do that and now we have our things so we can increment the count if we click it and it will increment that number in the top left you click it and our button turns red but we it's a pure component so it shouldn't be reuptake and so remember if we have any object literals in our render method it's creating those object literals every single time renders clicked a renderer happens and so since in our render here we have a peer button every single time this render is created this object is getting recreated and Jeff we remember back to day one we were talking about things like a stylesheet and so we can go ahead and use a stylesheet here which will guarantee that it won't create a new object every single time we render until let's do con styles equals a stylesheet create something you should be pretty familiar with at this point and let's have our button style be a line self-center and then go ahead and use it down here great so now it's not going to create a new style object to every single time rerender and so now we can see that we click it and uh it still turns red so even though we changed our object that was getting recreated every time we still have here a function literal and since we have just a literal function definition here is actually recreating that function every single render method as well and so every single time we render this pure button we're passing down a new function even though it does the exact same thing it's actually a completely new function reference and so what we can do here is declare a class property so you can say increment and all it does is this set state and takes a previous state and sets the count equal to the previous States count and add one let's so now down here rather than declaring a new function we can actually just use this dot increment and it's complaining but now it'll run if we click OK it's not turning red with that strange because we still have a string that we're just declaring here so why isn't Pierre componentry rendering even though we're declaring a new string literal here so if you remember all the way back to one of the first lectures we talked about the JavaScript primitive types we talked about how there were numbers there were many other types including strings and lastly there are objects and anything that wasn't one of those primitives was an object and every object gets recreated when you when you is so sorry the way that you compare these things when you compare them with triple equals objects their references will be changed and so if we declare a new object and we want to compare it by doing a triple equals if they're new if it's a new object no matter what's inside of it they're going to be different whereas for the primitives when you compare them with triple equals you're just seeing if their values are the same and so even though this is technically a new string that we've gone ahead and created when you compare those since it's the same exact string the peer component will know oh it's the same one I don't need to be render here and so that's please this yes lint and now this does behave how we actually wanted it to and why is that well it's because the title isn't changing the styles were not declaring in line we actually brought it out to a separate style object here and same thing with this function and you see it's no longer turning red and so the last common error Oh still the way that we fix this is by using constants or methods or properties on the classic instance which we just saw so let's look at the last very common error that I see which is unnecessary logic in a mount or an update so this one is a lot more subtle than the others but adding class properties to an instance so adding properties to that particular instance of a class instead of methods on the class and why is this bad well properties are created at every single mount whereas methods are created just once ever and so in other words when we create something like this which is the class property which is set equal to a function as I explained when we first talked about this syntax is basically the same as doing a constructor here invoking the super and then doing this dot increment equals a function that does this so that means every single time this app is or this component is constructed it creates a new function and says two equal to this whereas if we had instead done something like this this is a method and this method is only created once at the time of creating this module and so something like a radon map isn't created every single time we create a new array it's just something that lives on the array prototype and so it's only created once whereas here same thing if we if we implement increment as a method here it's only created once at the time of this modules creation rather than every single time this component gets mounted or created which is effectively effectively what happens when we do this as a class property as such and so this is one of the things that might get you because if you had actually done it as a class method like this what happens there's actually a bug here and we've seen this bug many times we'll click and you say oh this says state isn't it's not a function why is it not a function because what is this when increment gets invoked it's not this class who knows what it is and so there's actually a bug here and so we actually do need to bind this to the instance and so this is actually a time where it might not be worth implementing this small small optimization is that in fact it's you can't even do it in this case but there are there are cases where if you have something like render where every time renders implement invoked it's always going to be in the correct in this context that way we don't have to implement render as a class property so it's possible that we wanted to bind render to this class and we can do that by by using this notation but since every time render is invoked its using the right this context we don't have to and so that is a small optimization but again remember there are trade-offs every single for all these optimizations and what is it well these performance optimizations come at complexity costs and oftentimes it's just not worth the cost of complexity maintainability so don't forget don't over optimize until a bottleneck is found so let's go ahead and take a quick break and then after the break we're gonna look at a specific optimization built in to react native hello and welcome back so before the break we were talking about performance and a few of the common pitfalls in react and we ended with me reminding you that a lot of these pitfalls are less performance but it's not necessarily a bad thing oftentimes optimization comes at a cost that is too great the complexity that you end up adding to your app is not worth the marginal benefits that you get in terms of cost so let's talk about a time where often actually does matter to be as performant as possible and that's in animations and so if you remember back to project 1 we implemented what was a Pomodoro timer and so let's add a progress bar to that timer so this progress bar should show us how much time is left in the timer and so the animation that we're about to create is gonna require both the JavaScript and UI thread and so let's go ahead and do it so I have it running here so this is just a solution it has a work timer it'll switch to a break timer 25 minutes is probably too long for us to sit here and wait to see the progress bar go up so let's actually modify the code so the code is conveniently copied into the repo if you cloned it before class so let's actually first just take a quick look at exactly what this is doing so for those of you who took a look at the solution that I released a few weeks ago this is basically the exact same solution cut and pasted but let's just take a look at what is doing and so in app we declare a couple things you could clear the defaults for work minutes and break minutes just actually adjust those to be something like 0.1 minutes or 6 seconds each and so if we save that we'll see that it got reset to 6 seconds each but here we have a couple of things we have our state which has a work time and break time where the work time in break time are measured in seconds we then have something called time remaining which is the same thing but measured in milliseconds we have a flag ledger letting us know if the timer is running or if it's paused and we have a flag that lets just know if the active timers work or break when their component mounts we create a new timer I created a timer class set the state to be running and then every single time the timer clicks ticks we pass this function called update time remaining which is declared here which just sets the state it does a bunch of other stuff but let's go check a look at what the timer is how its implemented so let's look at the utils I created a timer class to encapsulate all of the logic for timing and so this timer takes a duration how long the timer should be in milliseconds it takes what should it do every time it ticks a function a callback there and what should it do when it hits zero and so it goes ahead and saves all of those values it then goes ahead and creates what should be the end time and it starts ticking and what happens every single tick well if the time is less than if the end time is less
Original Description
00:00:00 - Introduction
00:01:32 - Performance
00:02:03 - Trade-Offs
00:02:52 - Measuring Performance
00:18:24 - Common Inefficiencies
00:18:41 - Rerendering Too Often
00:46:11 - Unnecessarily Changing Props
01:00:40 - Unnecessary Logic in Mount/Update
01:04:05 - Reminder: Trade-Offs
01:04:59 - Animations
01:26:01 - Animated
01:43:46 - In Conclusion
This course picks up where Harvard University's CS50 leaves off, transitioning from web development to mobile app development with React Native, a popular open-source framework maintained by Facebook that enables cross-platform native apps using JavaScript without Java or Swift. The course introduces students to modern JavaScript (including ES6 and ES7) as well as to JSX, a JavaScript extension. Through hands-on projects, students gain experience with React and its paradigms, app architecture, and user interfaces. The course culminates in a final project for which students implement an app entirely of their own design.
https://www.youtube.com/playlist?list=PLhQjrBD2T382gdfveyad09Ierl_3Jh_wR
***
This is CS50, Harvard University's introduction to the intellectual enterprises of computer science and the art of programming.
***
HOW TO SUBSCRIBE
http://www.youtube.com/subscription_center?add_user=cs50tv
HOW TO TAKE CS50
edX: https://cs50.edx.org/
Harvard Extension School: https://cs50.harvard.edu/extension
Harvard Summer School: https://cs50.harvard.edu/summer
OpenCourseWare: https://cs50.harvard.edu/x
HOW TO JOIN CS50 COMMUNITIES
Discord: https://discord.gg/T8QZqRx
Ed: https://cs50.harvard.edu/x/ed
Facebook Group: https://www.facebook.com/groups/cs50/
Faceboook Page: https://www.facebook.com/cs50/
GitHub: https://github.com/cs50
Gitter: https://gitter.im/cs50/x
Instagram: https://instagram.com/cs50
LinkedIn Group: https://www.linkedin.com/groups/7437240/
LinkedIn Page: https://www.linkedin.com/school/cs50/
Quora: https://www.quora.com/topic/CS50
Slack: https://cs50.edx.org/slack
Snapchat: https://www.snapchat.com/
Watch on YouTube ↗
(saves to browser)
Sign in to unlock AI tutor explanation · ⚡30
Playlist
Uploads from CS50 · CS50 · 0 of 60
← Previous
Next →
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Hello, World: Hadi Partovi
CS50
Content Distribution and Archival in a Digital Age
CS50
CS50 2014 - Week 1
CS50
CS50 2014 - Week 3
CS50
CS50 2014 - Week 0, continued
CS50
CS50 2014 - Week 4
CS50
Week 3, continued
CS50
Quiz 0 Review
CS50
CS50 2014 - Week 3, continued
CS50
CS50 2014 - Week 7
CS50
CS50 2014 - Week 7, continued
CS50
Breaking Through The (Google) Glass Ceiling by Christopher Bartholomew
CS50
Introduction to Amazon Web Services by Leo Zhadanovsky
CS50
CS50 2014 - Week 9
CS50
How to Build Innovative Technologies by Abby Fichtner
CS50
Light Your World (with Hue Bulbs) by Dan Bradley
CS50
Building Dynamic Web Apps with Laravel by Eric Ouyang
CS50
CS50 2014 - CS50 Lecture by Steve Ballmer
CS50
CS50 2014 - Week 10
CS50
This is CS50 with Steve Ballmer?
CS50
Meteor: a better way to build apps by Roger Zurawicki
CS50
Data Analysis in R by Dustin Tran
CS50
Data Visualization and D3 by David Chouinard
CS50
CS50 2014 - Week 6
CS50
Build Tomorrow's Library by Jeffrey Licht
CS50
CS50 2014 - Week 9, continued
CS50
Essential Scale-Out Computing by James Cuff
CS50
iOS App Development with Swift by Dan Armendariz
CS50
Sam Clark Leads Yale Students on Tour to CS50 at Harvard
CS50
3D Modeling and Manufacture by Ansel Duff
CS50
CS50 2014 - Week 5, continued
CS50
hello, world
CS50
CS50 2014 - Deep Thoughts - Hash Table
CS50
CS50 2014 - Deep Thoughts - Binary Tree
CS50
CS50 2014 - Deep Thoughts - Scratch
CS50
CS50 2014 - Deep Thoughts - MySQL
CS50
LaunchCode Visits CS50
CS50
CS50 Live, Episode 100
CS50
CS50 Field Trip to Google
CS50
This is CS50 AP
CS50
Week 4: Monday - CS50 2011 - Harvard University
CS50
Week 2: Wednesday - CS50 2011 - Harvard University
CS50
Week 1: Wednesday - CS50 2011 - Harvard University
CS50
Week 11: Monday - CS50 2011 - Harvard University
CS50
Week 3: Wednesday - CS50 2011 - Harvard University
CS50
Week 12: Monday - CS50 2011 - Harvard University
CS50
Week 1: Friday - CS50 2011 - Harvard University
CS50
Week 3: Monday - CS50 2011 - Harvard University
CS50
Week 10: Wednesday - CS50 2011 - Harvard University
CS50
Week 2: Monday - CS50 2011 - Harvard University
CS50
Week 9: Monday - CS50 2011 - Harvard University
CS50
Week 7: Monday - CS50 2011 - Harvard University
CS50
Week 5: Monday - CS50 2011 - Harvard University
CS50
Week 5: Wednesday - CS50 2011 - Harvard University
CS50
Week 7: Wednesday - CS50 2011 - Harvard University
CS50
Week 8: Monday - CS50 2011 - Harvard University
CS50
Week 9: Wednesday - CS50 2011 - Harvard University
CS50
Week 8: Wednesday - CS50 2011 - Harvard University
CS50
Week 10: Monday - CS50 2011 - Harvard University
CS50
Week 2: Wednesday - CS50 2010 - Harvard University
CS50
More on: Frontend Performance
View skill →Related Reads
📰
📰
📰
📰
React Introduction
Dev.to · Karthick (k)
Why SnapDOM Beats html2canvas for DOM-to-Image Capture
Dev.to · Juan Martin
I built 42 landing page templates as single HTML files (no npm, no build step)
Dev.to · Segcam spa
Part 7B — Section 2 — React Event Handling Explained: Forms, Event Object & User Input.
Medium · JavaScript
Chapters (12)
Introduction
1:32
Performance
2:03
Trade-Offs
2:52
Measuring Performance
18:24
Common Inefficiencies
18:41
Rerendering Too Often
46:11
Unnecessarily Changing Props
1:00:40
Unnecessary Logic in Mount/Update
1:04:05
Reminder: Trade-Offs
1:04:59
Animations
1:26:01
Animated
1:43:46
In Conclusion
🎓
Tutor Explanation
DeepCamp AI