 Hello. So in my talk I will be discussing about React and Redux and how we could optimize our app. I will be discussing about the key takeaways from my project, which are the problems that I faced and how I solved those. So myself, Hina, and I am currently working at Zomato. I am working with the catalog team. So in catalog team, we mainly build menus. Everything related to menus comes under our team, and I am responsible for the menu tool that our merchant makes use of. So I have mentioned my GitHub handle and tech blog link as well. I have also shared my LinkedIn profile in case you want to connect with me. Before starting, let's first discuss in brief about React and Redux. So first of all, we know that it's declarative in nature. That means that we could divide our component into subcomponent and we could just specify our components, that is, what is to be done, rather than specifying how that is to be done. That is, we can break down our components into subcomponents. Another important aspect of React is it makes use of JSX. That is, we can combine our JavaScript with HTML like syntax. And another important principle of React is it supports one-way data flow. That is, there are certain immutable values that could be passed into our React component and that could not be directly edited, but we can set callback function that could do the modification. We also call those values as props, that is also known as properties. And this is also commonly known as actions flow up and properties flow down. Now, when it comes to Redux, there are three major principles that are involved with Redux. So for those who are not aware of those principles, the first one is it supports single source of growth. That is, within our React app, there will only be one store at a time that is needed because it helps to do faster Dev cycle. And apart from that, it helps to avoid duplicacy in the app. Another important principle of Redux is that changes are to be made using pure function. That means that we should not mutate our function. That is, we cannot directly make use of our input arguments and do modification into it. For example, if we have a multiplication or a division, we cannot just directly modify the input and mutate those. For a given set of input, there will be a specific set of output. And apart from that, the third one is the read-only state. That is, the store that is in the store always accept a read-only state. We cannot ever edit the state, but we can make it immutable in nature. This is important because it also helps us to affect the way we are showing our component, the way we are rendering our component. We are aware of the fact that we do shallow comparison in our component. And in case we are not mutating our props and state, that means that our React component is not aware that the state or the prop is actually changed. And it could lead to certain bugs that we are even want to be able to debug or it will be difficult to debug at our end in case we are mutating our data. So, we should ideally avoid that. Now, we must have noticed that the React apps are pretty much faster than the other JS framework. The main and the simple reason that is behind it is React makes use of virtual DOM. That is, instead of computing the entire change of the app, it just computes the change that is made in the browser by determining what all props and states are actually changed. And only those component which are actually making use of those states and props, that is, only those component in which those states and props are getting used gets re-rendered. So, that is done using virtual DOM. Now, let's discuss a brief about my project that is catalog, that is the menu tool. So, before getting started with it, I would like to share a bit about the performance scenario that is before the tool used to take around five seconds for a single edit operation. And after doing certain performance optimization, I was able to do drop that count to up to 0.5 seconds or even less than that. So, let's first discuss about the structure that I was getting for the menu tool. So, you must have ordered food from Zomato app. But behind the scene, the structure is a bit complex for the menus. So, you must have ordered an item or a combo or just a drink. But let's discuss about the structure of the menu. So, for a particular item, say for a North Indian food, let's consider Tawa roti. So, let's consider the roti section. So, it could be categorized into a group because all of these rotis could be combined into bread. Now bread could also be plain or stuffed bread. And within plain bread as well, we can classify the plain bread into multiple dishes, which could be Tawa roti, Tandoori roti or stuffed roti or onion kulcha and the list goes on. Now another important problem here is, we can further add combos here. For example, we can combine Tandoori roti with an item of another category, say misi roti or say we want to add combos to it. For example, we want to add Pepsi with a roti section. So, that would make the entire structure a bit convoluted. Now when it comes to menu tool, that is when we are rendering this entire menu, which is containing around 100 or 200 items, it was a bit difficult at first to do the optimization because the structure was a bit convoluted. The structure that was coming in the API response was not UI friendly. So, to optimize that, so first of all, before going into the problem statement ahead, the problem that was happening with the edit operation was even on making a single edit, for example, on changing the item name or say marking an item out of stock or marking a particular dish as restaurant specific, the rendering that was happening was in all the subcomponents. That is not just a particular dish component, but all the four component in the given example were getting re-rendered. The reason behind it is the prop and the states were not managed properly. That is immutability was happening, but that was not happening in the right manner. For example, in certain cases the entire list was getting passed in a dish component, which was not actually needed. So, we will be discussing about all these points in the following slides. So, first of all, for the performance improvement, I noticed that initially for the react component, we were extending the component class and should component update was not getting used in some of the components. So, to do away with that, I made use of pure component. The reason behind it is pure component helps us to do shallow comparison by default. So, we are aware of the life cycle methods that happens in the react component. So, one of the method is should component update. So, as soon as we do the shallow comparison between the props and the state, that is as soon as we compare the previous prop with the current prop and the previous state with the current state, we are able to figure out that the component is actually changed. And that comparison also is shallow in nature. That means that we are not doing deep comparison, which is a bit, which makes the app a bit slower because we are comparing, because in case we are doing deep comparison, then we are comparing each of the value in the object. So, first of all, we should ideally make use of pure component, that is the basics instead of using component class. So, as discussed just now, it handles the shallow comparison by default. We can also make use of component class by extending it, but in that case, please ensure to write should component update method and use shallow comparison within it. But since it is already provided to us using pure comparison, there is no need of extending component class. The next important point is never ever mutate the data. The reason behind it is simple. It makes the code buggy. And apart from that, it's difficult to diagnose those bugs because at there will be a point when you may notice that you have mutated the data and the reduct state is showing that the state is actually changed, but actually the state is not changed, that is the component is never re-rendered. Another important factor is in case we have the components in which we are not making use of the state of the component, that is we are not doing any sort of manipulation or we are not making use of any of the react state, then in that case, it's useful to use stateless component. So, stateless component simply accepts props in one of the function argument and we can do manipulation around that. And it is simple, it is similar to the render method that is in the react class, but we can just return the HTML like that is the JSX syntax or the simple strings that we want to return within the return by returning in the function itself. So, stateless components are also a cleaner way in case we are not manipulating any state within the component and it is also considered a bit faster. It also depends on our requirement as well. In case we have state in our component, then of course, we need to use the react class. Now, another important problem that I was facing was there was lot of data manipulation that was happening. For example, one of the scenario was in case I need to mark a dish out of stock, then the category also needs to reflected. For example, say for a particular dish, say for tawa roti, currently we are marking it out of stock for delivery and for takeaways, then in that case the category also needs to show that this category is partially available. That is that particular category is not fully enabled or fully disabled, but one of the item is currently not serviceable. So, in that case, I need to do that manipulation on the tool as well to show that in the drop down. So, to do away with that, I chose to make use of the concept of memoization. So, in the previous slide, one of the speaker mentioned about re-select and I had made use of that. It is one of the memoized selector that helps us to do that. But before going, before discussing about that, let's first discuss a bit about memoization. So, say for a given problem, if a problem could be broken down into sub-problem and those problems could be re-computed again and again and we know that that sub-problem is getting repeated in nature. That is, it is getting re-computed in nature. Then in that case, it's preferable to store the result of those sub-problems into cache and then make use of that output instead of re-computing it again and again. A common example that we must have observed is that happens is with Fibonics series. So, for example, in this scenario, the sub-problem is getting repeated again and again. For example, Fibonics of 2 and 2 is getting repeated again and again. Similarly, Fibonics of 1 is also getting repeated three times. So, we need to avoid that re-computation. The first reason is it helps us to reduce the scripting time and secondly, it also helps us to write a cleaner code because in that way, we know that our function will only be, it's more like our functions will only be called only in that case when the function argument is actually changed. That is, when our input is actually changed. So, one of the examples of re-select is this. So, in re-select, we first of all need to specify our logic. So, logic is nothing but a JavaScript method. It is a simple JavaScript method in which we can do our manipulation. So, I have just returned the number of, I have just returned a key from an object. That is, I have returned items from a shop object. We can, of course, do a manipulation here. We can write our logic here. So, this is our method which can accept the logic. We can also specify multiple logics in re-select. For the simplification, I have just written a simple logic method. And in the last argument, I can return the output. So, right now, I have returned the total count of item. But of course, we can change that. It all depends on our use case. But in this particular scenario, we will only be re-computing the number of items when the function argument is changed. That is, whatever argument we are passing here, only if those argument, that is, the reference of those argument is changed, then the inner logic will be re-computed. So, now that I got to know about certain performance improvements. Even after that, the app was not that fast. So, I noticed that the load time was a bit slower. So, I noticed that some of the items that were getting mounted were actually not needed. Because of the fact that I was just showing the first category as in expanded state, and the rest of the categories were in collapsed state. So, we know that when a particular component is in collapsed state, we are not showing it. That is, it is hidden in nature. So, in that case, it's better to just not mount it. Because in that case, we are entering into component dead mount of that component. And then we are calling the render method of that component. Even though we are not showing it anywhere in the screen. So, in that case, I just did conditional rendering, that is, render this particular component, that is, render the name only if it is visible in nature. Of course, the logic was a bit complex in this element. But it is just an example to show that we can do a similar logic in our code. Also, I also noticed that before doing performance improvement or rendering optimization, it is important to figure out exactly which component at which level we should start with to do the performance improvement. Because we either we can, if we start doing performance improvement blindly in all the component, it might consume more time to us. And in case we have certain deadlines, it's important to know that which component is most affected. In my case, the items component, the dishes component was the one that was getting mounted more times than categories or subcategories. So, I knew that I had to optimize the dishes component before starting with categories and subcategory. So, before starting before coding, it's important to first diagnose what is the problem and which component is the most affected and start with it. Also, I also recently I also noticed a scenario in which in a particular component, due to a particular case in component did update, the component was getting rendered multiple times. And it was important to diagnose that. So, that was happening due to a error. And because of that, I realized that it is important to capture exceptions. So, to do that, you can integrate a error tracking tool and keep a track of what error you are facing. And you can also make use of error boundaries for that. It is important to capture exceptions because it actually helps us to do the performance improvement in our app. Because without that, it is important to diagnose the scripting errors which might be causing, which might be increasing the scripting time and which might be increasing the load time in general. So, I figured out two points that is to specify, it's important to add error boundaries in the code for that. And secondly, I thought of having an error tracking tool integrated with the app for that. So, for error tracking tools, I found out three error tracking tools that are majorly used, but I went with Sentry because it's open source and it has an admin panel in which I can easily assign the bugs within the team so that I could keep a track of which person is working on which error. And apart from that, I was able to see the stack trace as well and I was able to see which device the user was on, at what time the user was on. And I can tag, I can also do tagging with the exceptions. For example, I wanted to tag REST IDs and user IDs with the menus. For example, if a particular merchant is making menu, I wanted to know which user was working on it and which REST ID he was on. So I was able to do that as well. Apart from that, of course, such dashboards helps us to keep a track of errors and it helps us to resolve those bugs a bit easily because we know that what is the stack trace and which person is working on which bug. So with respect to error boundaries, we can make use of a lifecycle method of React, which is component did catch. So within component did catch, we can either set a state or we can do one thing. We can integrate an error tracking tool and capture exceptions there. In my case, I made use of sentry, so I had to integrate it using raven. So I did raven.capture exception within component did catch. So I was able to capture exceptions that are specific to rendering using this method and also it is important to keep these error boundaries as granular as possible. The reason behind it is in case our app is not loading for a particular error or a particular exception, then in that case, it's not needed to not load the entire app. We can just show an error occurred in a particular subcomponent and at least load the rest of the components that are in the app, so that the user is at least able to show the rest of the information. For example, one of the scenario in menu tool was some of the dishes component were missing from the categories and subcategory while syncing it. So in that case, initially I was showing error occurred on the entire app and later I changed it in the way that the merchant was able to see the menu, but it was in disabled state and I was showing some catalogs that is some dishes component are missing. So that the merchant is aware of the fact that some components are missing, but he was able to know what dishes components still exist in the menu. Now, let's discuss some of the dev tips that will be useful. So first of all, since we know that react is declarative in nature, it is important to break the component into some component. I realize that had I written the code in a single file or in a single component, it was actually impossible or too difficult to debug that the dish component is actually slow. So it's important to break the component into some component and make the code modular. That way, we can easily do performance improvement and rendering optimizations as well. Now, next thing is in case we are making certain generic component, for example, say for drag and drop, there is a certain piece of logic that is only specific to our code and we have written a wrapper around drag and drop. Then in that case, we should ensure that it is generic enough to accept default values. And in case we are not passing any particular property, it should not break and it should not throw an exception for that. Also, we should only make use of one UI framework. For example, and or semantic, in Zomato, we make use of sushi, but we can, of course, choose other frameworks as well. But to maintain consistency, it's important to choose one design framework that is suiting our requirement. And it's important to add a readme file that helps the new contributors to get started with the project. And of course, we should always add linting configuration as well that helps us to maintain a consistent and cleaner and intended code everywhere. Now, there are certain safety steps. First of all, within render method, we should never do set state because it will ultimately lead maximum stack size exceeded error because we will end up calling a render method infinite times, not infinite, but up to the stack size. Secondly, mutation is not acceptable because it will lead to those shady errors which will be difficult to diagnose. And it will be hard to tell why our component is not updated. And then maybe some of the developer might end up calling force update, but it is not actually a good practice to do that. It is actually important to diagnose the error and then fix it instead of doing hacky code everywhere. Also, it's important to know that we should make use of arrow function because arrow function helps us to bind the context. That is, we are aware of which react component, which class we are on. Otherwise, we will have to bind that method using bind method. And we will have to bind the context of that method. Also, within componented update as well, we should not directly make use of set state. We should always check whether that prop or that state is actually changed in which we are setting the, in which we want to, in which condition we want to set the state. The reason behind it is, we always enter into componented update when any of the prop or any of the state is actually changed. Also, for cleaner code, it's important to destructure the code. Now that we are on ES, like we are at least using ES6, we should destructure the code and we can set default values while destructuring as well. Also, please feel free to contact me for any sort of discussion on my personal email. And this is my Github handle.