1 00:00:00,120 --> 00:00:02,430 - Now the next hook I wanna talk about is the use ref hook, 2 00:00:02,430 --> 00:00:05,220 which is unfortunately by far the most annoying hook to work 3 00:00:05,220 --> 00:00:06,750 with in React when it comes to TypeScript, 4 00:00:06,750 --> 00:00:08,280 'cause they made some really weird decisions 5 00:00:08,280 --> 00:00:09,390 when they created it. 6 00:00:09,390 --> 00:00:11,460 So you notice immediately I have multiple errors inside 7 00:00:11,460 --> 00:00:13,410 of my code with this code that I have written here. 8 00:00:13,410 --> 00:00:15,870 So I have an input ref, and I just set it to a use ref, 9 00:00:15,870 --> 00:00:18,057 and I'm trying to define that on my input down here. 10 00:00:18,057 --> 00:00:20,850 You may think that this should work fine but it doesn't. 11 00:00:20,850 --> 00:00:22,290 Obviously if I hover over this area, 12 00:00:22,290 --> 00:00:24,306 you'll notice it's really confusing what's going on. 13 00:00:24,306 --> 00:00:26,460 The reason that this is so confusing 14 00:00:26,460 --> 00:00:28,885 is because this ref prop right here inside of React, 15 00:00:28,885 --> 00:00:31,080 they either expect you to pass undefined, 16 00:00:31,080 --> 00:00:33,690 which obviously we're not doing, or a legacy ref. 17 00:00:33,690 --> 00:00:35,207 So if we go a little further and look at this legacy ref, 18 00:00:35,207 --> 00:00:36,900 you'll notice it can be a string. 19 00:00:36,900 --> 00:00:38,610 Just ignore that, that's legacy. 20 00:00:38,610 --> 00:00:39,840 That's why they call it legacy ref, 21 00:00:39,840 --> 00:00:41,160 or it expects a ref. 22 00:00:41,160 --> 00:00:42,840 And this ref object here 23 00:00:42,840 --> 00:00:45,750 is either a callback or it's going to be a ref object. 24 00:00:45,750 --> 00:00:46,920 This callback is how we talked 25 00:00:46,920 --> 00:00:49,140 about how you can use the use callback hook inside a ref. 26 00:00:49,140 --> 00:00:50,880 So this obviously doesn't apply. 27 00:00:50,880 --> 00:00:51,720 So the only thing we care 28 00:00:51,720 --> 00:00:54,210 about right here is this either ref object 29 00:00:54,210 --> 00:00:55,949 or it expects us to pass along null. 30 00:00:55,949 --> 00:00:58,077 And a ref object is just a normal object 31 00:00:58,077 --> 00:00:59,770 that has a current property on it. 32 00:00:59,770 --> 00:01:01,907 So it either expects us to pass along a ref 33 00:01:01,907 --> 00:01:04,109 or a value of null, 34 00:01:04,109 --> 00:01:07,770 but specifically we cannot pass undefined. 35 00:01:07,770 --> 00:01:11,469 A ref must always be null or an actual ref object 36 00:01:11,469 --> 00:01:13,230 when we pass it to an input. 37 00:01:13,230 --> 00:01:15,150 And you'll notice that this by default sets 38 00:01:15,150 --> 00:01:17,040 to undefined 'cause we pass in nothing. 39 00:01:17,040 --> 00:01:19,290 So we actually need to pass along null into this, 40 00:01:19,290 --> 00:01:21,360 because now we actually get a ref object 41 00:01:21,360 --> 00:01:23,250 that is null and not undefined. 42 00:01:23,250 --> 00:01:24,083 So if we look at this, 43 00:01:24,083 --> 00:01:25,680 you can see it's an object that has the type 44 00:01:25,680 --> 00:01:27,690 of null as the default type. 45 00:01:27,690 --> 00:01:28,620 So it's really important 46 00:01:28,620 --> 00:01:30,832 if you're ever using an HTML element and you wanna hook 47 00:01:30,832 --> 00:01:33,960 up the ref, you need to set knoll as the value. 48 00:01:33,960 --> 00:01:35,880 Another thing that you need to do when you're working 49 00:01:35,880 --> 00:01:37,560 with an actual ref is you need to type it, 50 00:01:37,560 --> 00:01:40,290 because right now this is a type specifically of only null. 51 00:01:40,290 --> 00:01:41,831 It can be nothing except for null. 52 00:01:41,831 --> 00:01:45,090 So obviously when I come in here, do input ref.current 53 00:01:45,090 --> 00:01:46,890 and I wanna get like the value of my input 54 00:01:46,890 --> 00:01:50,070 or I wanna focus on my input, none of that's working at all. 55 00:01:50,070 --> 00:01:51,030 Instead, I need to pass 56 00:01:51,030 --> 00:01:52,890 in the generic here, and I need to pass 57 00:01:52,890 --> 00:01:55,020 in the HTML input element. 58 00:01:55,020 --> 00:01:56,580 Pretty much every single HTML element, 59 00:01:56,580 --> 00:01:58,620 you can just start with all capitals, HTML, 60 00:01:58,620 --> 00:02:00,120 and then search for whatever your element is. 61 00:02:00,120 --> 00:02:01,740 In my case, it's an input element, 62 00:02:01,740 --> 00:02:03,390 and that's going to give me the type for that. 63 00:02:03,390 --> 00:02:05,400 And now you can see that I hover over this, 64 00:02:05,400 --> 00:02:08,130 it is saying that this is a type of HTML element. 65 00:02:08,130 --> 00:02:10,350 And if I make sure I just put in the question mark here, 66 00:02:10,350 --> 00:02:11,790 because this is possibly null 67 00:02:11,790 --> 00:02:13,770 'cause it can be null or an HTML element, 68 00:02:13,770 --> 00:02:15,994 you can now see everything is working just fine. 69 00:02:15,994 --> 00:02:16,860 And if I go 70 00:02:16,860 --> 00:02:19,710 to this use ref definition right here, 71 00:02:19,710 --> 00:02:21,750 you'll notice that it returns to us a ref object, 72 00:02:21,750 --> 00:02:22,583 and if we go to this, 73 00:02:22,583 --> 00:02:23,960 you can see that this is an immutable object, 74 00:02:23,960 --> 00:02:25,110 it is read-only. 75 00:02:25,110 --> 00:02:26,760 So it's really important to understand 76 00:02:26,760 --> 00:02:28,740 that this is giving me back a read-only version. 77 00:02:28,740 --> 00:02:31,500 So I can't actually set my current to anything at all. 78 00:02:31,500 --> 00:02:33,037 If I tried to set something, it's essentially saying, 79 00:02:33,037 --> 00:02:35,222 "Hey this is read-only, I cannot set it." 80 00:02:35,222 --> 00:02:38,287 So if you pass along Noel to a ref, you're telling React, 81 00:02:38,287 --> 00:02:39,120 "Hey, you know what? 82 00:02:39,120 --> 00:02:40,740 You handle this ref for me. 83 00:02:40,740 --> 00:02:43,020 I don't wanna mess with this ref, you handle it for me." 84 00:02:43,020 --> 00:02:45,000 And I'm only pretty much going to do that in the case 85 00:02:45,000 --> 00:02:46,550 where I pass it to a component like this. 86 00:02:46,550 --> 00:02:48,750 But sometimes you have a ref, for example, 87 00:02:48,750 --> 00:02:50,460 this value ref, where you don't want to pass it 88 00:02:50,460 --> 00:02:52,380 to a component and you wanna be able to mutate it yourself 89 00:02:52,380 --> 00:02:54,067 'cause you want to handle this reference yourself. 90 00:02:54,067 --> 00:02:55,770 In those cases, you essentially need 91 00:02:55,770 --> 00:02:58,200 to do the exact same thing but don't pass along null. 92 00:02:58,200 --> 00:03:00,060 So here, I need to give it a generic type 93 00:03:00,060 --> 00:03:02,538 because right now it's just assuming the type is undefined. 94 00:03:02,538 --> 00:03:04,350 So here I'll give it a generic type, 95 00:03:04,350 --> 00:03:06,360 and we're saying that this is a number. 96 00:03:06,360 --> 00:03:08,400 If I do that, you can now see my code works fine 97 00:03:08,400 --> 00:03:09,870 and this is either undefined 98 00:03:09,870 --> 00:03:12,060 or it's going to be an actual number. 99 00:03:12,060 --> 00:03:13,320 Or if I pass it a default, 100 00:03:13,320 --> 00:03:14,790 I can just remove this generic type 101 00:03:14,790 --> 00:03:16,770 because it just assumes what the value's gonna be. 102 00:03:16,770 --> 00:03:18,870 You can see it assumes it is going to be a number 103 00:03:18,870 --> 00:03:20,846 and now again everything is working just fine. 104 00:03:20,846 --> 00:03:22,230 So ref is really annoying 105 00:03:22,230 --> 00:03:23,520 in the way that they implemented it. 106 00:03:23,520 --> 00:03:24,690 If you want to use a ref 107 00:03:24,690 --> 00:03:26,717 with an input component or an HTML element, 108 00:03:26,717 --> 00:03:28,980 you need to make sure that you pass along the generic 109 00:03:28,980 --> 00:03:31,380 for what the HTML element is and then pass along 110 00:03:31,380 --> 00:03:32,460 null as the default value, 111 00:03:32,460 --> 00:03:34,200 'cause if you don't do this, it's not going to work, 112 00:03:34,200 --> 00:03:35,190 you're gonna get an error. 113 00:03:35,190 --> 00:03:36,896 And if you're using a ref that just has not 114 00:03:36,896 --> 00:03:39,360 a HTML element hooked up to it, 115 00:03:39,360 --> 00:03:40,980 never pass no as the default value. 116 00:03:40,980 --> 00:03:42,990 'cause if you do that, you're going to mess everything up. 117 00:03:42,990 --> 00:03:45,090 It's going to think you want to work with an HTML element 118 00:03:45,090 --> 00:03:46,650 and it's not gonna let you mutate it. 119 00:03:46,650 --> 00:03:47,483 Instead, you need 120 00:03:47,483 --> 00:03:49,380 to either pass it undefined as the default value 121 00:03:49,380 --> 00:03:51,086 or whatever your actual default value is. 122 00:03:51,086 --> 00:03:53,781 And you may optionally need to specify the exact type here. 123 00:03:53,781 --> 00:03:55,416 If you either have no default value 124 00:03:55,416 --> 00:03:57,726 or you have a really generic default value, 125 00:03:57,726 --> 00:03:59,310 like an array like this, 126 00:03:59,310 --> 00:04:01,440 you need to make sure you type it as a number array. 127 00:04:01,440 --> 00:04:02,700 And then if I change this to an array, 128 00:04:02,700 --> 00:04:04,650 you can see everything is working fine.