React Native, v2 useState, useCallback, useEffect
Transcript from the "useState, useCallback, useEffect" Lesson
>> It's all about Hooks. Now if you're already familiar with React, you're familiar with Hooks. But for those of you aren't this is quite an important section because React Hooks are basically how you do anything asynchronist in reaction. How you save state, it's how you do callbacks, it's how you do anything that's dynamic, and if you're gonna use function components instead of class components, you will have to use Hooks.
[00:00:27] Hooks actually quite a recent addition. They've only been in React maybe a year, but everyone's using them and so are we. Now there are quite a few built in Hooks, but generally the main ones that you need to know about are useState, useCallback and useEffect. And I'm going to go through each of these in turn.
[00:00:52] UseState is for saving and updating state inside your component. You will import it from React not React Native. They work exactly the same in React as you do in React Native by the way. So you import it from React, and the way to use it is inside a function component.
[00:01:09] So this you can't use in a class component and you cause can't use it outside a component, so this has to be inside a component before the return. And what we do here is we call useState with an initial value, so in this case the initial value is zero and it returns an array of two items.
[00:01:30] So here we use the array destructuring, and the first item which returns is the value, so this is the current value of the state and the second argument, so the second thing it returns is a function to set the value. Now there's two ways to set the value, you can either pass in a function, which takes the current value, and then you can use the current value to set the next value, or you can just simply set device directly without any reference to the current value.
[00:02:03] I added a little example, just to illustrate the useState [INAUDIBLE]. This takes a little while to warm up I might just launch this on my phone it might be quicker All right, so this is a little counter application that I wrote. This is what it looks like on my phone.
[00:02:57] So there's nothing special going on here. We've got a counter at the top left, and we've got 2 buttons for increment and decrement. So when I tap on increment, it goes up. When I tap on decrement, it goes down, so classic counter. I'm not going to do a to do list, I promise, and let's look at the code for this.
[00:03:19] Here I've used the use state from react. I've set the default values as zero, and I'm using count and set count. Notice that in my example here, I used value and set value. This is because it doesn't matter what you name them, it's up to you. So you can have as many useSates as you want.
[00:03:40] Now, as far as the code goes, I have just a text that displays the current account and then two buttons. I have one for increment and one for decrement. For this, I have an onPress handler, and both of these use the setCount, which was a second argument from useState.
[00:03:59] And both of these use the current value and either increment or decrement it, those that if I was to change this to lots of nines, then my starting value would be lots of nines. And if I just deleted it all together, I think oops. If I delete it all together, there would be no value.
[00:04:24] I think it wouldn't even work because, yeah, it would be a NaN because it's trying to add 1 to undefined. Right, so next up we have useCallback. useCollback is used for any actions you may want to perform be it a state update, a network request, or launching a modal.
[00:04:51] You don't have to use useCallback always, but is quite handy to know and in most of the applications that I worked at we tend to migrate all of our side effect in to useCallbacks. So looking at the country example that we had before, We would like to, yeah, so currently in that country example, we have the onPress handlers inline.
[00:05:19] So look at here yesterday inline, which is kind of fine because it's just a country, it just says do one thing, but it's not really great because if we had a longer on press, so instead, we kind of want to extract those into constant functions, like so. So now we have handle increment and handle decrement, which we can pass in.
[00:05:41] Now this works with the problem is that the way React works is every time there is a change either inside or outside the component, this component gets a re render. So everything inside the components gets recalculated, so especially if you were doing something complex inside here, this will get rerun every single time you do, like anything you are related in your application.
[00:06:05] This is why you might want to use useCallback. So instead of what we can do is we can put this exact function inside a useCallback. So if you notice that this and this are exactly the same. To use callback basically takes two arguments. The first, is the function that you want to execute, and the second is an array of variables.
[00:06:28] So here we use an empty array. What this array of variables does is, it basically tells you when you should recalculate this function. So especially this is only used if you use something outside of what's already here, if that makes sense. So if I was to use any okay, I will again show an example.
[00:06:58] All right, so okay, so this actually works in here, this is great. Right, so here I've got a count and a setCount. And I created a callback for handleIncrement and I created a callback for handleDecrement, so this works. And this works because I've used the current value for set count, but what if I just use this if I did this to be counted plus one, instead of the current value plus one.
[00:07:27] So now if I incremented it, no matter how often I increment it, it's still one. And that's because I'm using this count variable. And this gets cached, and in order for this function to get re-executed, then anything that you use inside this function that you want to make sure it's reflected, you have to add them here in the array.
[00:07:50] So now if I add count to this array and I start incrementing that increment works again. So that's why hooks are really handy and really powerful, but it's really easy to make mistakes like that. In general, if you have a hook and things aren't updating like looking whether you're passing everything you need to interdependencies array is a good place to start debugging.
[00:08:25] The last hook that we're going to look at is called useEffects. If you're already familiar with React, like React components then use effect is comparable to componented mounts, and componented updates. It's basically tied to the component lifecycle. It gets run generally when the component is initially mounted, and another part of it gets run when the component is unmounted.
[00:08:53] You would use this for example, when you want to subscribe to something during the converted life cycle, and you could also use it if you wanted to do some action based on the properties. Or if you wanted to do some action just once when the component is initially rendered.
[00:09:13] So here's an example, for a ChatAPI. So this is a effect that is run once, when the component is mounted. And this is a ChatAPI, we subscribe to messages. And when the component gets mounted, this gets run, so you subscribe. I noticed that useEffect actually returns a function.
[00:09:34] It doesn't always return a function, but it's may. And this is basically the cleanup part of the useEffect. If you do something in useEffect that has a potential for a memory leak, for example, subscribing to something you should also add a cleanup function which undoes that effect. In this case, we subscribe to the friend status when the component is launched.
[00:09:58] And then when the component is unmounted, we unsubscribed from friend status. All of these functions, you can have as many useEffects as you want. And all of these get run when the component is removed to an estate. And the other thing you might use it for is if you just want to do an action, well, once or multiple times, actually.
[00:10:22] So in this case, notice that it has a dependencies array, this action gets run just once. And you need to make sure that you pass this, otherwise it gets run every time the componentry renders. If you pass the parameter here, for example, this action would be run whenever that parameter changes.
[00:10:44] Let's look at an example. All right, so I have to use my phone for this, because the network request doesn't work for the in browser version. Cool, so basically what I'm doing here is I am fetching some cat facts from a public cat facts API. And I've got a state parameter here I've got useState.
[00:11:16] Which stores all the facts, so I'm using a facts to solve the array and I've got a set facts for updating the array. I'm gonna start with an empty array. Now I'm going to have a useCallback. And now have a useCallback which basically does the net request. So a little bit hard to see here because everything's open and I can't close it.
[00:11:47] Okay. So here I'm going to use call back. I'm doing an asynchronous call and this is the entire call. I'm going to fetch from this API and then I'm going to get the Jason from the cat facts, and then I'm going to set the facts here. And finally we've got a useEffect, and this is run when the component is initially launched and is going to call this function.
[00:12:19] Now, the reason that I had to do a useCallback, rather than doing all the fetching stuff in here is because you can't do asynchronous things in a useEffect. You can in a use effect you can trigger functions that are asynchronous, but this itself, if I tried to do this, it would just tell me no, it wouldn't run.
[00:12:41] And the other thing to notice that is that I said, so look at what my screen is that you need to be wary of making sure you remember to pass this in. So let's see what happens if I don't pass this then, you see that it just loads, and loads, and loads, and loads for requests and keys auto updating.
[00:13:04] That is because it gets rerun every time the component is rendered, and the component gets rendered every time something changes. So this will get triggered to get to this, which fetches this, which sets the fact and then this causes the component to re-render and you end up with an infinite loop.
[00:13:20] So you need to be quite careful in using these.