1
00:00:03,000 --> 00:00:06,225
Ok. So, we set up React Query in our application.

2
00:00:06,726 --> 00:00:10,053
Now, let's see how to use it to make an API request.

3
00:00:12,091 --> 00:00:14,803
And we'll start by our NavBar component,

4
00:00:14,803 --> 00:00:16,770
where we fetch the user data.

5
00:00:17,338 --> 00:00:19,623
What we're going to do is replace

6
00:00:19,623 --> 00:00:22,115
the "useState" and "useEffect" calls

7
00:00:22,685 --> 00:00:25,204
with a single call to "useQuery",

8
00:00:25,204 --> 00:00:28,106
that's a hook provided by React Query.

9
00:00:28,683 --> 00:00:32,134
The way this works is that we pass a "queryKey",

10
00:00:32,134 --> 00:00:35,227
that is a name used to identify this query.

11
00:00:35,227 --> 00:00:38,607
And we're free to choose whatever name we like,

12
00:00:38,607 --> 00:00:41,699
but this will be used when caching the data

13
00:00:41,699 --> 00:00:45,367
so it helps if it's a name that describes the data.

14
00:00:45,367 --> 00:00:48,675
That's why in this case I'm calling it "user".

15
00:00:49,535 --> 00:00:51,966
"useQuery" expects a second argument

16
00:00:51,966 --> 00:00:54,465
that is a function that will actually

17
00:00:54,465 --> 00:00:55,950
go and fetch the data.

18
00:00:56,586 --> 00:00:59,238
So in this case it will be similar to the code

19
00:00:59,238 --> 00:01:01,141
we already wrote for "useEffect".

20
00:01:01,699 --> 00:01:05,591
However in this case we need to return the user data,

21
00:01:05,591 --> 00:01:08,309
so it will be managed by React Query.

22
00:01:08,883 --> 00:01:10,488
Now, if there's an error,

23
00:01:10,488 --> 00:01:13,379
in this case we're treating an error response

24
00:01:13,379 --> 00:01:16,141
to mean that the user is not authenticated.

25
00:01:16,770 --> 00:01:19,997
So we could explicitly return "undefined" here,

26
00:01:19,997 --> 00:01:22,881
because that's the value we want to assign

27
00:01:22,881 --> 00:01:24,186
to the "user" data.

28
00:01:24,824 --> 00:01:27,429
Ok. Now, "useQuery" returns an object

29
00:01:27,429 --> 00:01:29,049
that I'll call "query",

30
00:01:29,620 --> 00:01:31,612
and this object has a number of properties,

31
00:01:32,520 --> 00:01:34,937
But all we need here is the "data",

32
00:01:34,937 --> 00:01:37,630
that in this case is our "user" object.

33
00:01:38,200 --> 00:01:41,158
Ok. At this point we can remove the old code.

34
00:01:43,466 --> 00:01:45,867
But now we have a small problem in that

35
00:01:45,867 --> 00:01:47,900
"setUser" doesn't exist any more.

36
00:01:48,462 --> 00:01:50,931
Let's just comment this out for the moment,

37
00:01:50,931 --> 00:01:52,883
and we'll come back to this later.

38
00:01:53,441 --> 00:01:55,213
Since we deleted the code

39
00:01:55,213 --> 00:01:57,483
using "useEffect" and "useState"

40
00:01:58,054 --> 00:01:59,826
we can remove this import as well.

41
00:02:00,326 --> 00:02:02,269
Ok. Let's go and test our application

42
00:02:02,269 --> 00:02:03,583
to see if it still works.

43
00:02:04,726 --> 00:02:07,384
Let's refresh the page, to start from scratch.

44
00:02:07,884 --> 00:02:10,374
If you notice, in the console logs,

45
00:02:10,374 --> 00:02:12,296
when the NavBar is rendered

46
00:02:12,296 --> 00:02:14,502
"user" is "undefined" at first,

47
00:02:14,502 --> 00:02:16,209
and then it gets updated

48
00:02:16,209 --> 00:02:18,629
with the data returned by the API.

49
00:02:19,414 --> 00:02:21,888
So this works exactly like it used to.

50
00:02:22,388 --> 00:02:24,711
Now, let's look at the network requests.

51
00:02:25,320 --> 00:02:27,921
Here we can see that it made a request

52
00:02:27,921 --> 00:02:29,564
to our "user" API route.

53
00:02:30,133 --> 00:02:32,609
Now, if we navigate to another page,

54
00:02:32,609 --> 00:02:34,810
it makes another "user" request.

55
00:02:35,379 --> 00:02:37,907
And if we go back to the HomePage,

56
00:02:37,907 --> 00:02:40,435
again it re-fetches the user data.

57
00:02:40,435 --> 00:02:43,781
So it's still making a new request every time

58
00:02:43,781 --> 00:02:45,640
and not caching the data.

59
00:02:45,640 --> 00:02:47,499
In fact, with React Query

60
00:02:47,499 --> 00:02:49,581
it makes even more requests.

61
00:02:50,453 --> 00:02:53,362
If I put the focus on the Dev Tools window,

62
00:02:53,862 --> 00:02:55,819
and then go back and click on the page,

63
00:02:56,319 --> 00:02:58,659
this triggers a new "user" request,

64
00:02:58,659 --> 00:03:00,999
which is quite surprising at first.

65
00:03:01,566 --> 00:03:03,940
But of course there's an explanation for this.

66
00:03:04,440 --> 00:03:06,747
Let's look at the React Query documentation.

67
00:03:08,140 --> 00:03:10,007
If we search for "useQuery"

68
00:03:10,007 --> 00:03:11,875
we can find the right page.

69
00:03:11,875 --> 00:03:14,989
When we call "useQuery" we pass a "queryKey",

70
00:03:14,989 --> 00:03:17,410
a query function to fetch the data,

71
00:03:18,118 --> 00:03:20,025
and then an object that can have

72
00:03:20,025 --> 00:03:21,635
many configuration options.

73
00:03:22,195 --> 00:03:24,378
So it's important that we configure

74
00:03:24,378 --> 00:03:25,875
our query appropriately.

75
00:03:25,875 --> 00:03:27,560
The first two arguments are

76
00:03:27,560 --> 00:03:29,930
the "queryKey" and the query function,

77
00:03:29,930 --> 00:03:31,303
as we've already seen.

78
00:03:32,053 --> 00:03:34,473
But if we look at the various options

79
00:03:34,473 --> 00:03:36,567
there is one called "stateTime".

80
00:03:37,133 --> 00:03:40,293
This is what we can use to cache the data.

81
00:03:40,293 --> 00:03:42,700
By default, "staleTime" is zero,

82
00:03:42,700 --> 00:03:46,537
which means the data will be re-fetched every time.

83
00:03:46,537 --> 00:03:48,870
That explains why at the moment

84
00:03:48,870 --> 00:03:51,353
we see all those "user" requests.

85
00:03:52,154 --> 00:03:55,015
Now, "staleTime" is not to be confused

86
00:03:55,015 --> 00:03:58,097
with this other option called "cacheTime".

87
00:03:58,671 --> 00:04:01,434
"cacheTime" specifies how long the data

88
00:04:01,434 --> 00:04:03,135
should remain in memory,

89
00:04:03,135 --> 00:04:05,403
so it's about memory management.

90
00:04:05,403 --> 00:04:07,387
If you request lots of data,

91
00:04:07,387 --> 00:04:10,293
like, in our website, if we were to fetch

92
00:04:10,293 --> 00:04:12,490
the data for each product page,

93
00:04:12,490 --> 00:04:14,829
then after a while, when the user

94
00:04:14,829 --> 00:04:17,380
is no longer looking at that product

95
00:04:17,380 --> 00:04:20,428
we could remove its data to free up memory.

96
00:04:21,495 --> 00:04:23,497
But "staleTime" is actually

97
00:04:23,497 --> 00:04:25,203
the most useful option,

98
00:04:25,203 --> 00:04:27,947
because that's what tells React Query

99
00:04:27,947 --> 00:04:30,246
how long the data is valid for.

100
00:04:30,969 --> 00:04:33,828
We'll soon see how to use it in our code anyway.

101
00:04:34,735 --> 00:04:37,229
Now, there's another option called

102
00:04:37,229 --> 00:04:38,917
"refetchOnWindowFocus",

103
00:04:38,917 --> 00:04:40,972
and this defaults to "true".

104
00:04:41,619 --> 00:04:44,295
So this is what's causing our user data

105
00:04:44,295 --> 00:04:47,933
to be fetched whenever we focus on a different window

106
00:04:47,933 --> 00:04:50,473
and then go back to the browser page.

107
00:04:50,473 --> 00:04:51,571
The idea is that

108
00:04:51,571 --> 00:04:54,454
if the user switches away from our website

109
00:04:54,454 --> 00:04:56,857
and then comes back after some time

110
00:04:56,857 --> 00:04:58,984
we may want to refresh the data

111
00:04:58,984 --> 00:05:00,975
to make sure it's up to date.

112
00:05:01,956 --> 00:05:04,971
This makes sense if the data changes frequently,

113
00:05:04,971 --> 00:05:08,176
like in your Facebook or Twitter feeds for example.

114
00:05:08,739 --> 00:05:10,869
But it's also good in our case,

115
00:05:10,869 --> 00:05:13,480
because the JSON web token can expire,

116
00:05:13,480 --> 00:05:17,122
so if the user goes away from our website for a while

117
00:05:17,122 --> 00:05:19,870
when they come back we may want to check

118
00:05:19,870 --> 00:05:21,726
if the token is still valid

119
00:05:21,726 --> 00:05:24,337
by calling the "user" API route again.

120
00:05:25,181 --> 00:05:27,477
Anyway, let's go back to our code

121
00:05:27,477 --> 00:05:29,635
and set some options by passing

122
00:05:29,635 --> 00:05:31,792
a third argument to "useQuery".

123
00:05:32,432 --> 00:05:34,482
This is an object that can contain

124
00:05:34,482 --> 00:05:37,619
any of the settings we've seen in the documentation.

125
00:05:38,180 --> 00:05:40,445
But let's start with "staleTime",

126
00:05:40,445 --> 00:05:41,750
that as I mentioned

127
00:05:41,750 --> 00:05:44,359
is the most important one for caching.

128
00:05:44,997 --> 00:05:48,808
The "staleTime" value is a number of milliseconds.

129
00:05:49,308 --> 00:05:53,618
Let's set this to "30_000" milliseconds for example.

130
00:05:53,618 --> 00:05:57,929
This means the user data will be considered "stale",

131
00:05:57,929 --> 00:06:00,167
or "old", after 30 seconds.

132
00:06:00,167 --> 00:06:04,146
In other words, it will be valid for 30 seconds,

133
00:06:04,146 --> 00:06:05,970
and expire after that.

134
00:06:06,802 --> 00:06:08,607
Let's see what difference this makes

135
00:06:08,607 --> 00:06:09,559
to our application.

136
00:06:10,268 --> 00:06:11,999
When we first load the page

137
00:06:11,999 --> 00:06:13,346
as usual it will make

138
00:06:13,346 --> 00:06:15,654
a first request to the "user" route.

139
00:06:16,283 --> 00:06:18,265
Now, if we go to a product page,

140
00:06:18,265 --> 00:06:21,302
this time it doesn't make any additional request.

141
00:06:21,864 --> 00:06:24,957
And same thing if we go back to the HomePage,

142
00:06:25,457 --> 00:06:28,412
or in fact if we focus on a different window,

143
00:06:28,412 --> 00:06:31,040
and then put the focus back on the page.

144
00:06:31,606 --> 00:06:33,891
You cans see that there's still

145
00:06:33,891 --> 00:06:37,209
only a single request in the Developer Tools.

146
00:06:37,209 --> 00:06:38,904
So what happens is that

147
00:06:38,904 --> 00:06:42,296
the NavBar component is mounted on every page,

148
00:06:42,296 --> 00:06:44,065
and this calls useQuery,

149
00:06:44,065 --> 00:06:46,277
but there is already some data

150
00:06:46,277 --> 00:06:49,668
in the React Query cache for the "user" query,

151
00:06:49,668 --> 00:06:52,544
so "useQuery" returns the cached value,

152
00:06:52,544 --> 00:06:54,977
without making a new API request.

153
00:06:56,067 --> 00:06:58,625
Now, if we wait 30 seconds however,

154
00:06:58,625 --> 00:07:01,842
so that the cached data will become "stale",

155
00:07:02,416 --> 00:07:04,919
even after 30 seconds there's still

156
00:07:04,919 --> 00:07:06,707
a single "user" request".

157
00:07:07,279 --> 00:07:11,143
So it's not like React Query will fetch new data

158
00:07:11,143 --> 00:07:14,283
automatically after exactly 30 seconds.

159
00:07:14,864 --> 00:07:16,934
But if we open another page now,

160
00:07:16,934 --> 00:07:19,847
this will trigger another call to "useQuery",

161
00:07:20,412 --> 00:07:23,916
and this time it does make another API request,

162
00:07:23,916 --> 00:07:26,898
because the old data that's in the cache

163
00:07:26,898 --> 00:07:28,016
is now "stale".

164
00:07:28,666 --> 00:07:32,076
But after that it will not make any request

165
00:07:32,076 --> 00:07:34,773
for another 30 seconds (at least).

166
00:07:35,353 --> 00:07:37,616
So that's how caching works,

167
00:07:37,616 --> 00:07:40,445
and it's one of the main advantages

168
00:07:40,445 --> 00:07:42,143
of using React Query.

169
00:07:42,805 --> 00:07:45,367
Now, we saw in the documentation that

170
00:07:45,367 --> 00:07:48,277
there's another option called "cacheTime".

171
00:07:48,277 --> 00:07:49,731
But this doesn't tell

172
00:07:49,731 --> 00:07:52,571
if the data in the cache is valid or not,

173
00:07:52,571 --> 00:07:55,134
it only says when this data should be

174
00:07:55,134 --> 00:07:57,974
removed from the cache to free up memory.

175
00:07:57,974 --> 00:08:00,953
In this case we're fetching the "user" data

176
00:08:00,953 --> 00:08:04,139
that's displayed on every page of our website,

177
00:08:04,139 --> 00:08:06,078
so we always need this data.

178
00:08:07,133 --> 00:08:10,309
We can tell React Query to keep it forever

179
00:08:10,309 --> 00:08:13,107
by setting "cacheTime" to "Infinity".

180
00:08:13,683 --> 00:08:16,027
Where Infinity, as you probably know

181
00:08:16,027 --> 00:08:18,697
is a special numeric value in JavaScript.

182
00:08:19,263 --> 00:08:21,905
Now, we can't really test "cacheTime".

183
00:08:22,405 --> 00:08:25,781
But let's test what happens if we are signed out.

184
00:08:26,281 --> 00:08:28,265
And I'll have to reload the app

185
00:08:28,265 --> 00:08:29,802
for the state to update,

186
00:08:29,802 --> 00:08:31,786
because of that "FIXME" comment

187
00:08:31,786 --> 00:08:33,578
in the "handleSignOut" code,

188
00:08:33,578 --> 00:08:35,115
that we'll fix later on.

189
00:08:35,871 --> 00:08:38,097
If we look at the network requests,

190
00:08:38,097 --> 00:08:40,004
the "user" route returned 401,

191
00:08:40,567 --> 00:08:43,076
as expected since we're not authenticated.

192
00:08:43,076 --> 00:08:45,405
But if we look at the Console messages,

193
00:08:45,965 --> 00:08:48,576
here we can see that in the NavBar

194
00:08:48,576 --> 00:08:51,802
the "user" variable was first "undefined",

195
00:08:51,802 --> 00:08:54,798
then the request to "/api/user" failed,

196
00:08:54,798 --> 00:08:58,332
and as a result the NavBar was rendered again,

197
00:08:58,332 --> 00:09:01,481
but with "user" still set to "undefined".

198
00:09:02,288 --> 00:09:04,295
If we go back to the network requests,

199
00:09:04,855 --> 00:09:06,080
we should see that

200
00:09:06,080 --> 00:09:08,667
even if we navigate to different pages

201
00:09:08,667 --> 00:09:11,322
it doesn't make any additional request.

202
00:09:11,322 --> 00:09:14,113
So it is caching "undefined" as the value

203
00:09:14,113 --> 00:09:15,543
for the "user" query.

204
00:09:16,316 --> 00:09:17,821
Which is exactly what we want.

205
00:09:18,682 --> 00:09:21,701
So this is how the "useQuery" hook works.

206
00:09:21,701 --> 00:09:25,236
We pass a key that's used when caching the data,

207
00:09:25,236 --> 00:09:28,330
a function that actually does the fetching

208
00:09:28,330 --> 00:09:30,465
and some options to configure

209
00:09:30,465 --> 00:09:32,454
the behaviour of the cache,

210
00:09:32,454 --> 00:09:34,516
and possible other settings.

211
00:09:34,516 --> 00:09:38,493
"useQuery" returns an object that includes the "data".

212
00:09:38,493 --> 00:09:40,261
And that "data" could be

213
00:09:40,261 --> 00:09:42,618
freshly fetched from the server,

214
00:09:42,618 --> 00:09:44,312
or come from the cache.

215
00:09:44,312 --> 00:09:46,595
React Query manages that for us

216
00:09:46,595 --> 00:09:50,056
depending on the options we passed in useQuery.

