1
00:00:02,070 --> 00:00:05,470
<v Maximilian>Now, as a final step in this application,</v>

2
00:00:05,470 --> 00:00:09,760
I wanna come back to this button in the header,

3
00:00:09,760 --> 00:00:12,040
to this HeaderCartButton.

4
00:00:12,040 --> 00:00:14,290
Everything works in this application,

5
00:00:14,290 --> 00:00:17,350
but I wanna play a little animation on this button

6
00:00:17,350 --> 00:00:20,200
whenever we add an item to the cart,

7
00:00:20,200 --> 00:00:22,150
or also when we remove an item,

8
00:00:22,150 --> 00:00:25,133
so whenever the amount of items in the cart changes.

9
00:00:26,200 --> 00:00:29,730
And for this, I already prepared something in the CSS file

10
00:00:29,730 --> 00:00:32,170
which I provided to you earlier.

11
00:00:32,170 --> 00:00:34,460
I set up a little CSS animation here

12
00:00:34,460 --> 00:00:37,823
which makes the button bump and change its scale.

13
00:00:38,780 --> 00:00:41,840
Now, we just need to make sure that this class,

14
00:00:41,840 --> 00:00:43,520
which starts this animation,

15
00:00:43,520 --> 00:00:46,433
this CSS class is added to the button.

16
00:00:47,340 --> 00:00:51,680
And for this, here I'll add a little const btnClasses,

17
00:00:53,810 --> 00:00:56,980
and I'll simply set this equal to a string

18
00:00:56,980 --> 00:01:00,270
using the template literal notation with back ticks

19
00:01:00,270 --> 00:01:02,430
instead of single quotes.

20
00:01:02,430 --> 00:01:05,553
And here, I will always add classes.button.

21
00:01:06,590 --> 00:01:11,100
But then, conditionally, I wanna add the animation class.

22
00:01:11,100 --> 00:01:13,840
Now, to show you how it works, I will add it right away,

23
00:01:13,840 --> 00:01:16,440
not conditionally but always for the moment.

24
00:01:16,440 --> 00:01:18,543
And that's the bump class.

25
00:01:19,850 --> 00:01:22,120
And now, here, for a class name on the button,

26
00:01:22,120 --> 00:01:25,223
I set this equal to btnClasses.

27
00:01:26,470 --> 00:01:27,327
If you save that and reload,

28
00:01:27,327 --> 00:01:29,810
you'll see this bump animation here.

29
00:01:29,810 --> 00:01:32,700
It only plays one, but later it should play

30
00:01:32,700 --> 00:01:34,713
whenever this cart changes.

31
00:01:35,800 --> 00:01:38,883
To make that happen, we can utilize useEffect.

32
00:01:40,220 --> 00:01:43,720
We haven't used it thus far in this application

33
00:01:43,720 --> 00:01:48,530
because we had no traditional side effect up to this point,

34
00:01:48,530 --> 00:01:52,610
no local storage access, nothing like this.

35
00:01:52,610 --> 00:01:54,540
Of course, you could add such features,

36
00:01:54,540 --> 00:01:56,190
but here we simply don't have it.

37
00:01:57,040 --> 00:01:59,900
Therefore, here I will utilize useEffect

38
00:01:59,900 --> 00:02:01,740
to play this animation.

39
00:02:01,740 --> 00:02:03,960
And therefore, here in the HeaderCartButton,

40
00:02:03,960 --> 00:02:05,707
I'll import useEffect,

41
00:02:07,190 --> 00:02:12,190
and then call useEffect here in this component function.

42
00:02:12,490 --> 00:02:15,020
Now, we pass our effect function to that

43
00:02:15,020 --> 00:02:17,693
and then our array of dependencies as you learned.

44
00:02:18,990 --> 00:02:20,900
Now here, in this effect function,

45
00:02:20,900 --> 00:02:24,220
I wanna do one simple thing in the end.

46
00:02:24,220 --> 00:02:25,790
I wanna change my btnClasses

47
00:02:25,790 --> 00:02:29,480
to include the bump animation class,

48
00:02:29,480 --> 00:02:33,610
and then I wanna set a timer which removes that class again

49
00:02:33,610 --> 00:02:38,230
so that when it's added again in the future, it again plays.

50
00:02:38,230 --> 00:02:41,560
So therefore, I will also import useState

51
00:02:41,560 --> 00:02:43,700
because we'll need to reevaluate

52
00:02:43,700 --> 00:02:45,520
and re-render this component

53
00:02:45,520 --> 00:02:49,053
when that animation class is added conditionally.

54
00:02:50,010 --> 00:02:51,513
So here, I'll call useState,

55
00:02:52,480 --> 00:02:56,210
set this to false initially because this will control

56
00:02:56,210 --> 00:02:58,960
whether or not the button should be animated,

57
00:02:58,960 --> 00:03:01,720
and I'll name it btnIsHighlighted,

58
00:03:05,310 --> 00:03:08,653
and setBtnIsHighlighted.

59
00:03:09,540 --> 00:03:12,480
Of course, the state names are up to you.

60
00:03:12,480 --> 00:03:16,912
Here, in useEffect, I'll then call setBtnIsHighlighted

61
00:03:16,912 --> 00:03:18,123
and set this to true.

62
00:03:20,970 --> 00:03:24,833
Then, as a next step, here for my btnClasses,

63
00:03:25,932 --> 00:03:28,570
I will not always add the bump class,

64
00:03:28,570 --> 00:03:32,160
but I'll check if btnIsHighlighted is true.

65
00:03:32,160 --> 00:03:35,130
And if that's the case, classes.bump is added,

66
00:03:35,130 --> 00:03:37,070
otherwise an empty string is added,

67
00:03:37,070 --> 00:03:40,223
so no extra CSS class is added then.

68
00:03:41,480 --> 00:03:44,170
And I do this here because, since I'm updating the state,

69
00:03:44,170 --> 00:03:47,790
the whole component will re-execute when that state changes.

70
00:03:47,790 --> 00:03:49,700
So this line will also change again,

71
00:03:49,700 --> 00:03:53,020
and the updated classes will be picked up down there.

72
00:03:53,020 --> 00:03:55,200
Now, of course, I don't always

73
00:03:55,200 --> 00:03:57,760
wanna change the state though.

74
00:03:57,760 --> 00:04:02,220
I only wanna change it if my items changed

75
00:04:02,220 --> 00:04:05,290
and if the length is greater than zero,

76
00:04:05,290 --> 00:04:08,853
so if there is at least one item in the cart, let's say.

77
00:04:10,120 --> 00:04:15,120
Hence, here I will check if cartCtx.items.length

78
00:04:15,670 --> 00:04:19,160
is equal to zero, in which case here I'll just return

79
00:04:19,160 --> 00:04:22,450
so that the rest of this effect function doesn't execute.

80
00:04:22,450 --> 00:04:24,060
Because this should only execute

81
00:04:24,060 --> 00:04:26,663
if we have at least one item in the cart, let's say.

82
00:04:27,620 --> 00:04:30,350
Now, we need to add this as a dependency.

83
00:04:30,350 --> 00:04:32,950
But if I add cart context like this,

84
00:04:32,950 --> 00:04:35,990
this effect would rerun whenever anything

85
00:04:35,990 --> 00:04:37,890
about my cart context changes.

86
00:04:37,890 --> 00:04:39,563
And that's not what I want here.

87
00:04:40,690 --> 00:04:44,780
Therefore, I'll use object de-structuring

88
00:04:44,780 --> 00:04:49,780
to pull out the items, to get them out of my cart

89
00:04:49,800 --> 00:04:52,940
so that here I can just refer to items

90
00:04:52,940 --> 00:04:56,670
and pass items as a dependency,

91
00:04:56,670 --> 00:04:59,970
so that not the entire context, but only the items array

92
00:04:59,970 --> 00:05:02,473
is a dependency for this effect function.

93
00:05:03,380 --> 00:05:07,120
Of course, we can also pull this out a little bit earlier.

94
00:05:07,120 --> 00:05:11,023
And, for example, also then refer to just items here.

95
00:05:14,330 --> 00:05:17,140
Now, if we save this, if I reload,

96
00:05:17,140 --> 00:05:20,630
if I click add, watch the button in the top-right corner.

97
00:05:20,630 --> 00:05:25,000
It now bumps, but only the first time I add something.

98
00:05:25,000 --> 00:05:28,430
The reason for that is that then this class is added,

99
00:05:28,430 --> 00:05:30,920
but since it's currently never removed,

100
00:05:30,920 --> 00:05:32,640
thereafter, it never changes

101
00:05:32,640 --> 00:05:35,190
because the animation is actually only played

102
00:05:35,190 --> 00:05:38,360
when this class is added for the first time.

103
00:05:38,360 --> 00:05:40,960
Therefore, we should also remove the class

104
00:05:40,960 --> 00:05:42,830
after the animation finished.

105
00:05:42,830 --> 00:05:45,083
And I'll do that by setting a timer here.

106
00:05:45,980 --> 00:05:50,110
I'll set a timer which fires after 300 milliseconds

107
00:05:50,110 --> 00:05:53,790
because that's the duration of this animation here.

108
00:05:53,790 --> 00:05:56,170
I played over 300 milliseconds,

109
00:05:56,170 --> 00:06:00,550
so after that duration, I trigger a function

110
00:06:00,550 --> 00:06:04,220
where I set btnIsHighlighted back to false.

111
00:06:04,220 --> 00:06:05,730
And if that's false,

112
00:06:05,730 --> 00:06:09,060
this here will ensure that an empty string is added

113
00:06:09,060 --> 00:06:12,720
to the classes string instead of the bump class.

114
00:06:12,720 --> 00:06:16,203
So that will remove that CSS class from the render to DOM.

115
00:06:18,070 --> 00:06:20,910
Now, I also wanna add a cleanup function

116
00:06:20,910 --> 00:06:23,500
where I clear that timer

117
00:06:23,500 --> 00:06:26,023
in case that component should be removed.

118
00:06:27,030 --> 00:06:29,270
This can't happen in this application,

119
00:06:29,270 --> 00:06:30,970
the button is always there,

120
00:06:30,970 --> 00:06:34,070
but it's still a good practice to clean up any timers

121
00:06:34,070 --> 00:06:37,440
or any other side effects that might be ongoing

122
00:06:37,440 --> 00:06:40,390
because you started them in useEffect.

123
00:06:40,390 --> 00:06:42,890
So here, I'll return my cleanup function.

124
00:06:42,890 --> 00:06:46,050
You learned that if you return a function in useEffect,

125
00:06:46,050 --> 00:06:47,800
this will be called automatically

126
00:06:47,800 --> 00:06:50,470
as a cleanup function by React.

127
00:06:50,470 --> 00:06:52,923
And here, I'll call clearTimeout and clear that timer,

128
00:06:54,850 --> 00:06:58,350
so that when this effect reruns, we clear the timer.

129
00:06:58,350 --> 00:07:01,890
And actually we do need this here now that I think about it

130
00:07:01,890 --> 00:07:04,530
because, of course, this timer can be set again

131
00:07:04,530 --> 00:07:06,140
before it expired.

132
00:07:06,140 --> 00:07:10,240
If we add multiple items rapidly after each other,

133
00:07:10,240 --> 00:07:12,650
we wanna clear the old timer

134
00:07:12,650 --> 00:07:15,310
and make sure that a new timer is set

135
00:07:15,310 --> 00:07:17,320
and the old timer is, well, cleared.

136
00:07:17,320 --> 00:07:20,330
So we definitely should have that cleanup function here.

137
00:07:20,330 --> 00:07:21,383
And now we do.

138
00:07:22,250 --> 00:07:24,980
And with that, if we save this, if I reload,

139
00:07:24,980 --> 00:07:29,350
you see, whenever I add an item, this button bumps.

140
00:07:29,350 --> 00:07:31,670
And that's just a little visual tweak,

141
00:07:31,670 --> 00:07:36,240
and in addition, as a nice side effect, no pun intended,

142
00:07:36,240 --> 00:07:40,220
it's another practice and exercise of useEffect,

143
00:07:40,220 --> 00:07:42,763
which you need for handling side effects.

