 Okay, so let's get started. So, hello everyone. Today I'm going to be talking about understanding React hooks as a backend developer. And I'm going to be assuming a little bit of knowledge about React. You don't have to be super familiar with React, but I'll be glossing over a few details. So this will probably make a little bit more sense if you have used React before in the past. So who am I? My name's Eric and I'm a senior developer with Previous Next. And back in the days when website frontends were mostly built with CSS and JavaScript or more aptly jQuery, I tended to work on both the frontend and the backend of projects. But over the years, as more and more frameworks came about, became harder and harder for me to keep up with them all. So especially as a professional, I have to consider maintainability when I'm building projects. And I found that it was getting difficult to maintain projects built on so-called hype frameworks that were all the rage at the time, but in six to 12 months when I needed to update them didn't have the support there anymore. So I tended a lot more towards back and development. So for me, at least it still feels like the frontend world moves pretty fast. And as you can see by this chart here, there's still a few choices of frameworks available today, just in case you needed some more discussion points at your next planning meeting. But a few years ago, Previous Next started taking on more and more decoupled projects and I decided that it was time for me to start learning React. So React has been around for a while now and it feels like it's going to be around for some time. So I started learning how to use React and I learned that there were essentially two types of components. The first one, a functional component, like this simple example here, which is basically just something with a render method. And for me, this kind of felt similar to a twig template. Occasionally there'd be a small amount of logic in there, but usually it was just something to wrap the render. So these components are quite limited and they can only take props. And if you wanted to be able to access things like the React lifecycle events or state, you needed to use a class component. So this is an example of a class component, which you're likely familiar with if you've been using React, but this is also essentially what's being replaced by React hooks. So here you can pass in some props, you have a little bit of state and then you have a render method where everything comes together at the end. And this is a basic example of a button component taking in a type prop there, has a little bit of state to track some clicks. And when I first went this, it reminded me of something that was a little bit more familiar with at the time. So my backend developer brain sort of saw this as similar to a block in Drupal. Now obviously this isn't a perfect one-to-one mapping and you might notice that the code here is a little bit inaccurate, but it was initially helpful for me to use this to build my understanding. So to me, passing in props felt a little bit like loading config, setting state felt a little bit like loading something from the database. And at the end, they both have some kind of render or build method where everything comes together. And to keep things simple, I didn't include any lifecycle methods like component did mount, but that kind of felt similar to overriding something in block base. But React decided that there was a hopefully better way to do things. So in React 16.8, they released react hooks. And this allows you to access state and other lifecycle events without writing a class or converting your component to a class. And thankfully there were no breaking changes in this release, which means that you don't have to rush out and upgrade all your components. But this is an approach that they'll be taking going forward. So it is advised to use this approach if you're writing new components. And from the React website, what is a hook? A hook is a special function that lets you hook into React features. For example, use state is a hook that lets you add react state to function components, which we'll be chatting about shortly. And when would I use a hook? If you write a function component and you realize you need to add some state to it, previously you had to convert it to a class, but now you can use a hook inside of an existing function component. So what hooks are available? There are quite a few hooks, so unfortunately can't cover them all today. And it's also possible to create your own hooks, which is quite useful. But essentially hooks are just normal JavaScript functions. They only have two special React specific rules, and that is the first one. Only call hooks at the top level. So don't call hooks inside loops, conditions or nested functions. And the second rule is only call hooks from React function components. Don't call hooks from regular JavaScript functions. Now you can however call hooks from React hooks from your custom hooks. So briefly, you might also be wondering why would we React want to use hooks? What's wrong with classes? And in their release documentation about the change, they gave a few reasons for this change. So the first one is it's hard to reuse stateful logic between components. So many React applications were finding themselves in a state of wrapper hell, trying to use providers, consumers, high order components and render props to share stateful logic and essentially hoisting things higher and higher and higher in the application so that they had shared state. And this meant that you had to write a lot of additional components and constantly restructure your hierarchy as your complexity increased. Hooks essentially solved this problem by allowing you to reuse stateful logic without changing your component hierarchy. So the second reason they gave is complex components became hard to understand. So in class components, as your component got more complex, you may have noticed that you had to put more and more unrelated logic together with certain life cycle methods like component did now. And it was difficult or sometimes impossible to break these components into smaller components. So the code was getting a little bit ugly. So an example of this may have been, you might have been loading some data from an external endpoint in component did now, but also setting up completely unrelated event listeners there. So hooks solve this by allowing you to split your component into smaller functions as appropriate instead of using a life cycle method. And the third reason that they gave was, they found classes confuse people and it was causing potential issues in compiler optimizations in the future. So in order to say relevant, the React team was looking ahead of time at better compiling and better processors here. And they found that in a lot of cases, class components were encouraging unintentional patterns that made optimization quite difficult. Another good point they made there was that classes in JavaScript can be a little bit tricky to understand, especially because of the way this works in JavaScript, which is a little bit non-standard with other programming languages. And they didn't really want that to be a barrier to entry. So let's jump back to our magic button component from before, and it's rewritten as a functional component using React hooks. So the first thing that you'll notice is, it's not a class. This is however, functionally the same as a class component. And you can see that we're passing in a type prop. We still have our state, which is counting the number of clicks. And we also have a button with an on click event. And then finally, we return some markup to tell React how to render the component. And this brings us to the first new hook we're going to look at, which is use state. So this is a new way to set default state and to create a way to update state in your component. So in this example, we're creating a count constant and we're also getting a set count function. And then we're calling use state with a default state for count, which in this case is zero. So it's fine for count to be a constant here because we should only ever read that variable. We should never try and write to it. If we want to update state, we need to do it in a way that React is aware of so that it knows when to re-render, which is why we get the set count function back there. And you can see we're using set count in the on click event as well. So here's a different example of a coffee deprived React developer with a drink coffee function, which updates the number of cups of coffee today. So each state variable has a separate constant and a default value. And it also gets its own set function as well. When you're working on components in the real world, it's very likely that you'll end up with more than one or two state variables. So I can get a little bit out of control if you need to have a declaration like this for each of them. Or perhaps in some instances, you may have bits of state that are very closely related. So for one example, I was working on a map component with a marker and it needed to track the lat and long in state. And it didn't really make sense to have them as separate declarations because I was never updating lat or long. It was always both at the same time. So I made a little bit more sense to put these into one state variable. And luckily for us, there's a way to do that with use state as well. And if you're familiar with React, you probably use something similar in a class component previously. So now I have just one state variable developer state here, which contains three bits of hopefully related state. One important difference to note here is that when you're updating only some of the state and not all the values, you need to be careful not to wipe the other values. So to do that, instead of passing a new value to set state, you can pass a function, which gives you the previous state as a variable. And that allows you to use the object spread syntax to add in other keys and then just update the part that you want. So you can see here in the drink coffee function, we're taking the previous state as an argument using the object spread syntax so that we don't override the hunger and tiredness. And we're only updating the cups of coffee today. One last thing to touch on here is that you might be tempted to put all of your variables into a single state object there, like on the previous slide, but I would actually encourage you not to do that. So if you have a few variables that are closely related, like in the marker lat long example, it makes a lot of sense, sure, but otherwise it's better to split them out into separate variables. And one of the reasons for this is that some React hooks can take state variables as dependencies and they use those dependencies to know when to rerun. So we'll look at an example of that a little bit later. So if you've been paying attention, you may have noticed that React really cares about how you read and write state. And that's because React uses state to determine when to rerender components. In fact, all React re-renders are triggered by a state change. So there used to be a function to force update, but that's since been deprecated and removed. So after component has had a state change, which triggers a re-render, all of the descendants are also re-rendered as well. And at first glance, that might sound really inefficient, but actually it's a lot more efficient than React trying to compare each of the child components and figure out if they've changed or not, and then re-render them selectively. To err on the safe side, React just re-renders everything from the parent down. And the reason for this is that React assumes that your components aren't pure. So a pure component is a component that would always produce the same result, given certain props, such as this example on the left, just taking a name and it'll always render a high name. And, but it doesn't take much to corrupt a pure component and turn it into something impure. So on the right here, we have an impure component and we've corrupted it simply by rendering the date there. So the first component will always render the same value given the same prop, whereas the second component, sorry, will always show a different value every time it's rendered regardless of the prop passed in. So because React assumes that your components aren't pure, it's safer for React to re-render all of the child components after a state change instead of risking showing outdated components. And something else to remember is that React is heavily optimized to make re-renders less expensive out of the box. It's basically built for rendering and re-rendering. So having a lot of re-renders is not necessarily a bad thing. Another benefit with React is that it only renders from the state change down. So not the entire app is re-rendered every time. So for the most part, you'll likely find that lots of re-rendering isn't a problem for smaller components. How can we optimize re-renders? So there are times when certain components do have expensive operations, or you may need a lot of re-renders. So React provides two hooks for us to optimize our components in these cases, which is useMemo and useCallback. More specifically, these hooks allow you to tell React that your component should be treated like a pure component. It doesn't need to be re-rendered unless some of the given dependencies change. So in other words, if we use these hooks to optimize our code, we want to either make a re-render less expensive or better yet, reduce the number of re-renders required for a given component, even though its parent is re-rendering. So I find it kind of easy to think of useMemo and useCallback as similar to caching in Drupal. Essentially, you're letting the system know, React or Drupal, that under certain conditions, the output or function doesn't need to re-run. So in this mental model example, we have our cacheability there, and we're adding the state variable as a cache tag. And this is essentially the same way that useMemo and useCallback work, but instead of cache tags, they're taking state variables or props as dependencies. So let's dive into an example where a component might be being re-rendered too often. So let's imagine Legal gets in touch with us and they let us know that we need to add some copyright text to our magic button before someone steals it for their own project. But we realize that having a standard copyright component would be pretty useful and that we could use it in other places in our app as well. So we create a copyright text component and all it does is render some static text. Now for this example, let's assume that we also move the clickCount text to its own component as well. And you don't need to understand these too much or be too familiar with them. Just essentially know that the copyright text will always render static text and that the clickCount text will always render text with the clicks prop in there as well. So to update the magic button component, we just need to import our new components and add it to the returned output. Once these changes are done, the component render tree would look something like this. So we'd have the magic button component on the top, clickCount text on the left, which takes a prop clicks and our copyright text to the right there. But as I mentioned before, when state changes, react re-renders all descendants. So if I were to click the magic button in this case, it would update the state and it would cause both clickCount text and copyright text to re-render. Now, although as we can see in this case, it's not really necessary to re-render copyright text because it's static and no matter what happens, the component will never change. So to improve this, we can use react's memo function to memoize the component so that it's only rendered once. Just by updating the export at the bottom, we can tell react that this is a pure component and it only needs to be changed if its props change. But in this case, there are no props so the component only ever needs to be rendered once. We could also make the same change to the clickCount text component and react would automatically consider the clicks prop as a dependency and only re-render that component when the prop is changed. But in the case of our very simple magic button example, the prop will always change when the state's been changed so it's kind of redundant here. This reduces the number of re-renders the component needs which was the first method of optimization I mentioned before. Sorry, the second one I mentioned before. And the memo function isn't technically a react hook but it basically works the same way as use memo which is why I wanted to cover it first before looking at the other way of optimization. So let's imagine we had another component which calculates pi to the nth digit and we let the user choose how many decimal places to be rendered by using input. Ascent has a simple on change event to recalculate pi as well. So essentially this component has some state and a really expensive operation that it has to undergo which in this case is calculating however many digits of pi. This is just an example. Obviously don't try and calculate pi like this you won't get very far. But from what we've covered about rendering so far we know that this component will only re-render when the decimal's input is updated with a new value assuming that this was used in a fairly isolated application and didn't have any parents. But what if we did something that caused this component to re-render a lot more frequently and didn't involve a change in the decimal's input? So let's say for example that for no particular reason we decided to add the time into this component and track the time in the state variable. This would cause the component to re-render every second and as a consequence recalculate the decimals of pi which is just wasted CPU cycles. So this is a great case for something like use memo. So let's see what this would look like afterwards. So it's a pretty small change overall to add use memo here but it's a really effective optimization in this case. So I've just wrapped that little bit of code in use memo and you'll notice that after return result I've also passed in decimal places as a dependency. So now instead of pi being recalculated every time the component re-renders or if we were tracking time every second it'll only be recalculated. If the decimal places state variable changes or in backend terms if our case is invalidated. So React also has another hook called use callback and this is functionally the same as use memo but it's designed for functions instead of arrays or objects like use memo. So in most cases you could restructure your code to achieve the same results with just use memo. So this is kind of syntactic sugar they basically work the same way. A common pattern you'll see in React is to pass an event handler to a component as a prop and as in this example here we now have a reset count function which we're passing to the new reset button component as a prop. It's important to remember that this is passing a reference and JavaScript doesn't compare functions by value or the code contained in them but just by reference. So even if we were to wrap our reset button module export in memo in the same way we did with copyright text in the example before it would actually still re-render every time every time the magic button re-renders sorry. So that's because every time magic button re-renders it creates a new version of reset count and it passes a new reference through which is considered different. So again we could just modify a reset count function to be wrapped in use memo and return a function but this is exactly what use callback was created for which is even easier. So just a small change here will let React know that the reset count function can persist between renders so that the reset button doesn't have to re-render if it wraps its export in memo as well. In this case we don't have any dependencies for use callback because the function doesn't change. So basically it would never get re-rendered sorry never get re-created but depending on what you're doing you can also pass in a state variable or a prop there as well. So React may or most likely will change in the future. So one final point to mention is that the React team has stated React in the future may choose to forget some previously memoized values and recalculate them to render for example to free memory for off-screen components. So you should write your code in a way that it still works without use memo and just use these afterwards to optimize for performance. So as a bit of a recap here it's recommended to write new stateful components with React hooks instead of using class components but the React team has said that they won't be deprecating class components anytime soon so you don't need to go in and rewrite your entire app but if you are creating new components I would advise to use this way. Hooks solve a variety of problems and ideally aim to make your code more legible and maintainable. You can use use state to manage state and functional components and you can use use memo or use callback to optimize your re-renders if you're doing complex operations. Any questions? Yeah. If the function is demo and callback they get deprecating in the future or the constant rejection would be open user. So essentially if they get deprecated in the future your code should still work without them and the only reason I can see that they would deprecate them would be if they're putting compiler optimizations in that do it automatically. So some way for React to realize on the fly that hey, this function or this value doesn't need to be recomputed unless this dependency changes. So removing them or having them should essentially be the same if they were to get deprecated. Which makes it easy for us. Thank you. Nice.