1
00:00:02,000 --> 00:00:04,000
Now, you can absolutely write

2
00:00:04,000 --> 00:00:07,000
this client side data fetching code on your own,

3
00:00:07,000 --> 00:00:10,000
as we did it here, there's nothing wrong with that.

4
00:00:10,000 --> 00:00:12,000
And you might have good reasons to do that

5
00:00:12,000 --> 00:00:15,000
because this, of course, gives you full control

6
00:00:15,000 --> 00:00:17,000
over the entire component state,

7
00:00:17,000 --> 00:00:20,000
and how exactly data is being fetched.

8
00:00:20,000 --> 00:00:23,000
But this is also such a common pattern

9
00:00:23,000 --> 00:00:27,000
that you could consider creating your own custom hook

10
00:00:27,000 --> 00:00:29,000
to outsource this logic into it,

11
00:00:29,000 --> 00:00:33,000
or to use a third-party hook created by someone else.

12
00:00:33,000 --> 00:00:37,000
And you can look into the SWR hook.

13
00:00:37,000 --> 00:00:42,000
If you Google for use SWR you will find swr.vercel.app.

14
00:00:43,000 --> 00:00:47,000
This is a React hook developed by the Next.js team,

15
00:00:47,000 --> 00:00:52,000
but you can use it in non-Next.js projects as well.

16
00:00:52,000 --> 00:00:53,000
In the end, this is a hook which,

17
00:00:53,000 --> 00:00:57,000
under the hood, still will send a HTTP request

18
00:00:57,000 --> 00:01:01,000
by default using the fetch API, which we also used,

19
00:01:01,000 --> 00:01:04,000
but it gives you a couple of nice built in features

20
00:01:04,000 --> 00:01:09,000
like caching and automatic revalidation retries on error.

21
00:01:10,000 --> 00:01:14,000
And you don't have to write all that code on your own.

22
00:01:14,000 --> 00:01:18,000
Instead, you can use this hook in a much simpler way.

23
00:01:18,000 --> 00:01:21,000
The strange name SWR, by the way, stands

24
00:01:21,000 --> 00:01:25,000
for stale-while-revalidate, which is the name of this hook

25
00:01:25,000 --> 00:01:30,000
because this hook has a built in features for caching data

26
00:01:30,000 --> 00:01:34,000
and revalidating data to give you the most up-to-date data

27
00:01:34,000 --> 00:01:38,000
without you noticing in a positive way, and so on.

28
00:01:38,000 --> 00:01:40,000
Now, you can dive into the docs

29
00:01:40,000 --> 00:01:42,000
of this hook to learn all about it

30
00:01:42,000 --> 00:01:45,000
because you can definitely also create

31
00:01:45,000 --> 00:01:47,000
a short course about this hook here,

32
00:01:47,000 --> 00:01:51,000
but getting started with it, thankfully, is super simple.

33
00:01:51,000 --> 00:01:54,000
In our project, we just need to quit the dev server

34
00:01:54,000 --> 00:01:57,000
and install it as a package.

35
00:01:57,000 --> 00:02:00,000
With npm install swr we install

36
00:02:00,000 --> 00:02:04,000
this SWR hook package into our project.

37
00:02:05,000 --> 00:02:09,000
Now, in last sales, if you want to use it, we can import it.

38
00:02:09,000 --> 00:02:14,000
We can import useSWR from 'swr' just like this.

39
00:02:16,000 --> 00:02:19,000
This imports the hook, it's the same example you see here.

40
00:02:20,000 --> 00:02:24,000
And now you can use this hook in your component,

41
00:02:24,000 --> 00:02:25,000
so not inside of useEffect,

42
00:02:25,000 --> 00:02:27,000
but directly in your component,

43
00:02:27,000 --> 00:02:30,000
all React hooks must be used directly

44
00:02:30,000 --> 00:02:33,000
in a component, not in some nested function.

45
00:02:33,000 --> 00:02:36,000
And we use it by simply executing it.

46
00:02:37,000 --> 00:02:40,000
Now, this hook wants at least one argument,

47
00:02:40,000 --> 00:02:43,000
which is an identifier for the request it should send,

48
00:02:43,000 --> 00:02:47,000
typically, the URL of that request.

49
00:02:47,000 --> 00:02:50,000
And it's also called an identifier

50
00:02:50,000 --> 00:02:53,000
because this hook will bundle multiple requests

51
00:02:53,000 --> 00:02:57,000
to the same URL, which are sent in a certain timeframe

52
00:02:57,000 --> 00:03:02,000
into one request to avoid sending dozens of small requests.

53
00:03:02,000 --> 00:03:07,000
Not an issue we'll have here, but nice to have in general.

54
00:03:07,000 --> 00:03:10,000
So, we can grab our URL here as an identifier

55
00:03:10,000 --> 00:03:12,000
because it will then conveniently use

56
00:03:12,000 --> 00:03:15,000
this identifier as a URL as well.

57
00:03:16,000 --> 00:03:20,000
And in the simplest form, this is all we have to do.

58
00:03:21,000 --> 00:03:25,000
You can add a second argument, which is a fetcher function

59
00:03:25,000 --> 00:03:27,000
which is a function that describes

60
00:03:27,000 --> 00:03:29,000
how the request should be sent.

61
00:03:29,000 --> 00:03:33,000
But the default is that it will use the fetch API.

62
00:03:33,000 --> 00:03:36,000
So, if we want to stick to that default, which I do here,

63
00:03:36,000 --> 00:03:39,000
we don't need to change anything.

64
00:03:39,000 --> 00:03:42,000
Instead, we just call useSWR, like this.

65
00:03:42,000 --> 00:03:45,000
And the request to this URL will be sent

66
00:03:45,000 --> 00:03:48,000
when this component is loaded.

67
00:03:48,000 --> 00:03:50,000
So, now, we can work with the data,

68
00:03:50,000 --> 00:03:52,000
which is returned by that hook.

69
00:03:52,000 --> 00:03:54,000
And that will be an object,

70
00:03:54,000 --> 00:03:57,000
which we can destructure therefore,

71
00:03:57,000 --> 00:04:01,000
which contains the data that was fetched eventually,

72
00:04:01,000 --> 00:04:04,000
and potential error information.

73
00:04:04,000 --> 00:04:08,000
So, I'll use the exact same object destructuring here

74
00:04:08,000 --> 00:04:11,000
and pull out the data, which we eventually get,

75
00:04:11,000 --> 00:04:13,000
and the error, which we might get.

76
00:04:14,000 --> 00:04:17,000
Down here, in our custom code, we have no error handling,

77
00:04:17,000 --> 00:04:19,000
but now we can easily implement it

78
00:04:19,000 --> 00:04:22,000
by just using this extra piece of data,

79
00:04:22,000 --> 00:04:24,000
which we get by the useSWR hook.

80
00:04:25,000 --> 00:04:29,000
So now, with that, we can comment out our custom hook.

81
00:04:29,000 --> 00:04:31,000
We could also delete it but I want

82
00:04:31,000 --> 00:04:33,000
to keep it around for a reference.

83
00:04:33,000 --> 00:04:37,000
We can also comment out our custom states though.

84
00:04:37,000 --> 00:04:40,000
And, now, we can work with data and error.

85
00:04:40,000 --> 00:04:44,000
If we don't have data yet, then we know that we're loading.

86
00:04:44,000 --> 00:04:48,000
So, here I'll check if not data,

87
00:04:48,000 --> 00:04:51,000
if we don't have data yet, then I return Loading...

88
00:04:51,000 --> 00:04:54,000
If we have an error, on the other hand,

89
00:04:54,000 --> 00:04:57,000
I wanna show an error message here, like Failed to load

90
00:04:58,000 --> 00:05:03,000
and we should move that in front of the, if data check

91
00:05:03,000 --> 00:05:06,000
because an error is more important than the loading state.

92
00:05:06,000 --> 00:05:08,000
If we have an error, I wanna show it.

93
00:05:10,000 --> 00:05:13,000
Now, if we don't have an error and we do have data,

94
00:05:13,000 --> 00:05:16,000
so if we make it past these two if checks,

95
00:05:16,000 --> 00:05:18,000
then we can output the data.

96
00:05:20,000 --> 00:05:22,000
Now, the problem we'll then face, however,

97
00:05:22,000 --> 00:05:25,000
is that, as I mentioned, the data we get back

98
00:05:25,000 --> 00:05:28,000
from Firebase is not in the right format.

99
00:05:28,000 --> 00:05:30,000
We need to transform it.

100
00:05:30,000 --> 00:05:34,000
Now, to work around that issue we got two main approaches.

101
00:05:34,000 --> 00:05:37,000
We could define our own fetcher function,

102
00:05:37,000 --> 00:05:40,000
you can learn about that here in the SWR docs,

103
00:05:40,000 --> 00:05:42,000
to basically fine tune

104
00:05:42,000 --> 00:05:45,000
how exactly data will be fetched and returned.

105
00:05:45,000 --> 00:05:48,000
Or we, again, use useEffect but,

106
00:05:48,000 --> 00:05:50,000
now, not for sending the request

107
00:05:50,000 --> 00:05:53,000
but for simply transforming the data.

108
00:05:53,000 --> 00:05:57,000
So then, here, our dependency would be the data which we get

109
00:05:57,000 --> 00:06:00,000
because I want to rerun this whenever we got new data.

110
00:06:00,000 --> 00:06:02,000
And in useEffect, I want to check

111
00:06:02,000 --> 00:06:05,000
if we do have data, because if we don't have data

112
00:06:05,000 --> 00:06:07,000
there is nothing we need to do.

113
00:06:07,000 --> 00:06:10,000
But if I do have data, then I wanna go

114
00:06:10,000 --> 00:06:12,000
through these transformation steps here.

115
00:06:12,000 --> 00:06:15,000
So, I'll copy this code from down there,

116
00:06:16,000 --> 00:06:21,000
comment this in, and then bring back my sales state here

117
00:06:21,000 --> 00:06:23,000
so that I can set this state

118
00:06:23,000 --> 00:06:27,000
after we transformed the data here in useEffect.

119
00:06:27,000 --> 00:06:30,000
So here, instead of this if check still,

120
00:06:30,000 --> 00:06:33,000
instead of useEffect, I'll then set my sales

121
00:06:33,000 --> 00:06:37,000
to the transform sales, which are now based

122
00:06:37,000 --> 00:06:41,000
on the data, the data key we're getting from useSWR.

123
00:06:43,000 --> 00:06:45,000
So, now, we have our own transformation logic here,

124
00:06:45,000 --> 00:06:48,000
which will be kicked off as soon as data was fetched.

125
00:06:50,000 --> 00:06:52,000
And that means that now, again, down there

126
00:06:52,000 --> 00:06:55,000
we can check that even if we have data

127
00:06:55,000 --> 00:06:57,000
it might not have been transformed yet.

128
00:06:57,000 --> 00:06:59,000
So, if we don't have sales yet,

129
00:06:59,000 --> 00:07:01,000
which is our transformed data,

130
00:07:01,000 --> 00:07:04,000
I still return a paragraph where I also say Loading...,

131
00:07:04,000 --> 00:07:06,000
for example, and of course, therefore,

132
00:07:06,000 --> 00:07:09,000
we can merge this and say if we don't have data

133
00:07:09,000 --> 00:07:13,000
or we don't have sales I want to return Loading...

134
00:07:13,000 --> 00:07:17,000
But if we do have both, then we can safely,

135
00:07:17,000 --> 00:07:18,000
again, output ours sales.

136
00:07:20,000 --> 00:07:22,000
And that's how we can now useSWR

137
00:07:22,000 --> 00:07:25,000
and still apply our own transformation logic.

138
00:07:26,000 --> 00:07:29,000
With all of that, if we now save this

139
00:07:29,000 --> 00:07:32,000
and restart the development server

140
00:07:32,000 --> 00:07:34,000
we should, again, have a working page.

141
00:07:34,000 --> 00:07:37,000
If we go back to last sales and reload,

142
00:07:37,000 --> 00:07:40,000
we see Loading... and, eventually, we see the data.

143
00:07:41,000 --> 00:07:43,000
And still, if I view the page source

144
00:07:43,000 --> 00:07:45,000
we don't see the data there,

145
00:07:45,000 --> 00:07:47,000
but instead we now see Loading...

146
00:07:47,000 --> 00:07:50,000
We see Loading... here because that is the starting state,

147
00:07:50,000 --> 00:07:53,000
the first initial version of this component,

148
00:07:53,000 --> 00:07:55,000
which is being rendered.

149
00:07:55,000 --> 00:07:57,000
Because initially error is undefined,

150
00:07:57,000 --> 00:07:59,000
so we don't return this.

151
00:07:59,000 --> 00:08:02,000
And data and sales are undefined,

152
00:08:02,000 --> 00:08:04,000
so we do return this and, therefore,

153
00:08:04,000 --> 00:08:07,000
that's what we see as part of the pre-rendered page.

154
00:08:07,000 --> 00:08:11,000
And, again, data fetching only happens on the client side.

155
00:08:11,000 --> 00:08:16,000
Now, using this hook, this useSWR hook, is not mandatory.

156
00:08:16,000 --> 00:08:19,000
As you saw, you can write your own logic,

157
00:08:19,000 --> 00:08:21,000
you don't need to use it.

158
00:08:21,000 --> 00:08:24,000
It just can be convenient to use this hook

159
00:08:24,000 --> 00:08:26,000
because you save a little bit of code,

160
00:08:26,000 --> 00:08:30,000
especially if you also would add error handling down there.

161
00:08:30,000 --> 00:08:34,000
And this hook, also has a bunch of other nice features,

162
00:08:34,000 --> 00:08:36,000
which we're not using here,

163
00:08:36,000 --> 00:08:38,000
but which can also be very handy.

164
00:08:38,000 --> 00:08:41,000
Like automatically re-fetching data when you lose

165
00:08:41,000 --> 00:08:45,000
and regain focus and other things like this.

166
00:08:45,000 --> 00:08:48,000
So that's something you can also look into.

167
00:08:48,000 --> 00:08:50,000
But, for the moment, that's all I wanted

168
00:08:50,000 --> 00:08:53,000
to show here because now we also know

169
00:08:53,000 --> 00:08:56,000
how we can implement client side data fetching.

