1
00:00:00,000 --> 00:00:02,000
So now that we improved

2
00:00:02,000 --> 00:00:05,000
this form submission experience,

3
00:00:05,000 --> 00:00:07,000
I wanna improve it even further.

4
00:00:07,000 --> 00:00:12,000
And I wanna make sure that we actually also tell the user

5
00:00:12,000 --> 00:00:16,000
if invalid data has been entered because at the moment,

6
00:00:16,000 --> 00:00:18,000
I would be able to submit an empty form,

7
00:00:18,000 --> 00:00:21,000
and that's, of course, not how it should work.

8
00:00:23,000 --> 00:00:25,000
Now, one way of adding validation

9
00:00:25,000 --> 00:00:29,000
is that we simply add some extra attributes

10
00:00:29,000 --> 00:00:31,000
to our form elements.

11
00:00:31,000 --> 00:00:34,000
The required attribute, for example,

12
00:00:34,000 --> 00:00:37,000
can be added to all the inputs and text areas

13
00:00:37,000 --> 00:00:41,000
to make sure that the browser shows an error automatically

14
00:00:41,000 --> 00:00:44,000
without us doing anything if such a field

15
00:00:44,000 --> 00:00:47,000
that's marked as required is empty.

16
00:00:49,000 --> 00:00:50,000
That's useful

17
00:00:50,000 --> 00:00:53,000
and something you definitely should consider doing

18
00:00:53,000 --> 00:00:57,000
because it's a quick and easy way of making your form safer

19
00:00:57,000 --> 00:00:59,000
and giving the user some feedback.

20
00:00:59,000 --> 00:01:04,000
But it's not enough because this can always be disabled.

21
00:01:04,000 --> 00:01:08,000
So here if I add it, a user would be able

22
00:01:08,000 --> 00:01:10,000
to inspect that form element

23
00:01:10,000 --> 00:01:13,000
and simply remove that required prop here,

24
00:01:13,000 --> 00:01:17,000
that required attribute, in the browser developer tools.

25
00:01:17,000 --> 00:01:20,000
Of course, not all users know about these tools,

26
00:01:20,000 --> 00:01:22,000
but a lot of users do.

27
00:01:22,000 --> 00:01:24,000
And therefore with that,

28
00:01:24,000 --> 00:01:27,000
I now would be able to submit the invalid form again.

29
00:01:27,000 --> 00:01:29,000
So that's not enough.

30
00:01:29,000 --> 00:01:30,000
It's a good first step

31
00:01:30,000 --> 00:01:33,000
to improve the user experience, but not enough.

32
00:01:33,000 --> 00:01:35,000
Therefore, you should actually also always

33
00:01:35,000 --> 00:01:38,000
validate submitted data on the server

34
00:01:38,000 --> 00:01:40,000
because that's the only place

35
00:01:40,000 --> 00:01:44,000
where the user can't do anything about your code.

36
00:01:45,000 --> 00:01:49,000
Hence, you should also validate the submitted data here

37
00:01:49,000 --> 00:01:52,000
in that server action.

38
00:01:52,000 --> 00:01:53,000
So here I wanna add a if check

39
00:01:53,000 --> 00:01:57,000
and check if title is maybe undefined

40
00:01:57,000 --> 00:02:01,000
or if title has a length,

41
00:02:01,000 --> 00:02:05,000
maybe after trimming it to remove excess white space,

42
00:02:05,000 --> 00:02:08,000
of zero, which means it would be an empty string.

43
00:02:09,000 --> 00:02:11,000
In that case, I have an error.

44
00:02:11,000 --> 00:02:14,000
The same is true if the content does not exist

45
00:02:14,000 --> 00:02:16,000
or is an empty string.

46
00:02:17,000 --> 00:02:19,000
And if I don't have an image,

47
00:02:19,000 --> 00:02:22,000
so if that's undefined or something like that,

48
00:02:22,000 --> 00:02:25,000
I also wanna return an error.

49
00:02:25,000 --> 00:02:28,000
So when one of these three if checks is met,

50
00:02:28,000 --> 00:02:30,000
I wanna return an error.

51
00:02:31,000 --> 00:02:33,000
Or actually, what I wanna do here

52
00:02:33,000 --> 00:02:37,000
is I wanna create an errors array,

53
00:02:37,000 --> 00:02:39,000
and then I wanna add new error messages

54
00:02:39,000 --> 00:02:42,000
for every check that fails.

55
00:02:42,000 --> 00:02:46,000
So here for the first check, I wanna add a new message

56
00:02:46,000 --> 00:02:49,000
to that array of error messages

57
00:02:49,000 --> 00:02:52,000
that, for example, says, "Title is required."

58
00:02:54,000 --> 00:02:56,000
And then for the second check,

59
00:02:56,000 --> 00:03:00,000
I wanna add a message that says, "Content is required."

60
00:03:00,000 --> 00:03:02,000
And for the third check,

61
00:03:02,000 --> 00:03:05,000
I add a message that says, "Image is required."

62
00:03:05,000 --> 00:03:06,000
That would be one way

63
00:03:06,000 --> 00:03:09,000
of constructing such an error message array.

64
00:03:11,000 --> 00:03:14,000
But of course, having that array here is not enough.

65
00:03:14,000 --> 00:03:16,000
We also need to get it back

66
00:03:16,000 --> 00:03:19,000
to the client side to update the DOM

67
00:03:19,000 --> 00:03:22,000
and show those error messages to the user

68
00:03:22,000 --> 00:03:26,000
in case they did try to submit an empty or invalid form.

69
00:03:26,000 --> 00:03:29,000
And how do we do that?

70
00:03:29,000 --> 00:03:31,000
Well, it would definitely be nice

71
00:03:31,000 --> 00:03:36,000
if we could simply check here in our server action

72
00:03:36,000 --> 00:03:40,000
if this errors array has a length that's greater than zero,

73
00:03:40,000 --> 00:03:42,000
which means it's not empty,

74
00:03:42,000 --> 00:03:45,000
which means we have at least one error.

75
00:03:46,000 --> 00:03:49,000
And if in that case, we could simply return an object here

76
00:03:49,000 --> 00:03:54,000
from our server action that includes that errors array

77
00:03:54,000 --> 00:03:55,000
as a property.

78
00:03:56,000 --> 00:03:58,000
That would be nice to do, right?

79
00:03:58,000 --> 00:04:00,000
If we could just return such an object,

80
00:04:00,000 --> 00:04:02,000
and then we could handle it on the client side.

81
00:04:02,000 --> 00:04:06,000
And it turns out we can do that.

82
00:04:06,000 --> 00:04:10,000
NextJS and React got us covered

83
00:04:10,000 --> 00:04:14,000
because React offers another form-related hook,

84
00:04:14,000 --> 00:04:17,000
the useFormState hook.

85
00:04:17,000 --> 00:04:20,000
So not useFormStatus, which we used before,

86
00:04:20,000 --> 00:04:21,000
but useFormState.

87
00:04:22,000 --> 00:04:24,000
And that's a hook that you can use

88
00:04:24,000 --> 00:04:29,000
to update the form-related UI you're showing

89
00:04:29,000 --> 00:04:31,000
to the user based on some state

90
00:04:31,000 --> 00:04:35,000
that may be changed upon the submission of a form,

91
00:04:35,000 --> 00:04:38,000
which is a complex way of saying you can use this hook

92
00:04:38,000 --> 00:04:43,000
to output any data you return from your formAction,

93
00:04:43,000 --> 00:04:45,000
from your server action in this case.

94
00:04:46,000 --> 00:04:50,000
Therefore, here, I'll import this

95
00:04:50,000 --> 00:04:55,000
useFormState hook from react-dom.

96
00:04:58,000 --> 00:05:03,000
Again, it's imported from react-dom, not from React itself.

97
00:05:03,000 --> 00:05:07,000
And we can now call this hook in our component

98
00:05:07,000 --> 00:05:11,000
that outputs the form, useFormState like this.

99
00:05:12,000 --> 00:05:16,000
So now I'm not calling it in some nested component

100
00:05:16,000 --> 00:05:18,000
as I did it with useFormStatus,

101
00:05:18,000 --> 00:05:21,000
which we called in the formSubmit component

102
00:05:21,000 --> 00:05:24,000
but instead directly in the component

103
00:05:24,000 --> 00:05:26,000
that also outputs the form.

104
00:05:27,000 --> 00:05:32,000
Now, useFormState then takes a value

105
00:05:32,000 --> 00:05:35,000
or actually, two values.

106
00:05:35,000 --> 00:05:40,000
And the first value this hook accepts is the formAction

107
00:05:41,000 --> 00:05:44,000
that should actually eventually be triggered

108
00:05:44,000 --> 00:05:45,000
when the form is submitted.

109
00:05:47,000 --> 00:05:48,000
So therefore, I'll actually call it

110
00:05:48,000 --> 00:05:50,000
after defining that formAction

111
00:05:52,000 --> 00:05:56,000
and then I will pass that formAction,

112
00:05:56,000 --> 00:05:59,000
this createPost function to useFormState

113
00:05:59,000 --> 00:06:01,000
as a first argument.

114
00:06:01,000 --> 00:06:03,000
I'm not executing it.

115
00:06:03,000 --> 00:06:06,000
Instead I'm just passing a pointer to this function

116
00:06:06,000 --> 00:06:08,000
as a first argument to useFormState.

117
00:06:10,000 --> 00:06:13,000
And then as a second argument,

118
00:06:13,000 --> 00:06:16,000
we pass some initial form state

119
00:06:16,000 --> 00:06:20,000
that should be used if the formAction has not executed yet.

120
00:06:20,000 --> 00:06:23,000
And here in my case, that will be an empty object

121
00:06:23,000 --> 00:06:27,000
because the form state I might eventually get

122
00:06:27,000 --> 00:06:31,000
will be this object that has an errors property,

123
00:06:31,000 --> 00:06:35,000
which contains an array of error messages.

124
00:06:35,000 --> 00:06:37,000
That's the form state we may eventually get

125
00:06:38,000 --> 00:06:41,000
because if the form submission succeeds,

126
00:06:41,000 --> 00:06:46,000
if we have valid data, we don't return any new state

127
00:06:46,000 --> 00:06:47,000
that should be shown on the screen.

128
00:06:47,000 --> 00:06:50,000
Instead, we navigate away here.

129
00:06:50,000 --> 00:06:53,000
So the only other state we can achieve is this errors state.

130
00:06:53,000 --> 00:06:57,000
But initially, we, of course, don't have any errors yet

131
00:06:57,000 --> 00:06:59,000
because the user didn't even have a chance

132
00:06:59,000 --> 00:07:01,000
of entering something.

133
00:07:01,000 --> 00:07:03,000
And therefore, my initial state for this form

134
00:07:03,000 --> 00:07:05,000
should be such an empty object

135
00:07:05,000 --> 00:07:08,000
and we'll use that state in just a second, no worries.

136
00:07:09,000 --> 00:07:12,000
But that's what we pass into useFormState.

137
00:07:14,000 --> 00:07:18,000
Then useFormState returns two values,

138
00:07:18,000 --> 00:07:20,000
exactly two values.

139
00:07:20,000 --> 00:07:24,000
Just like the standard useState hook

140
00:07:24,000 --> 00:07:25,000
that's built into React,

141
00:07:25,000 --> 00:07:28,000
that hook would also return an array

142
00:07:28,000 --> 00:07:31,000
with exactly two elements.

143
00:07:32,000 --> 00:07:35,000
useFormState is kind of similar, just related

144
00:07:35,000 --> 00:07:37,000
to forms you could say.

145
00:07:37,000 --> 00:07:40,000
It gives you the current form state.

146
00:07:40,000 --> 00:07:42,000
So that initial state initially

147
00:07:42,000 --> 00:07:44,000
and then thereafter, any other state

148
00:07:44,000 --> 00:07:48,000
that might have been returned by the formAction.

149
00:07:48,000 --> 00:07:50,000
The formAction you passed

150
00:07:50,000 --> 00:07:52,000
as a first argument to useFormState.

151
00:07:54,000 --> 00:07:57,000
And the second element you get back from useFormState

152
00:07:57,000 --> 00:08:00,000
will be an updated formAction,

153
00:08:00,000 --> 00:08:03,000
which is essentially this formAction,

154
00:08:03,000 --> 00:08:06,000
which you pass to useFormState.

155
00:08:06,000 --> 00:08:07,000
But this action here,

156
00:08:07,000 --> 00:08:09,000
which you get back from useFormState,

157
00:08:09,000 --> 00:08:11,000
is essentially such a formAction

158
00:08:11,000 --> 00:08:14,000
to which React is listening

159
00:08:14,000 --> 00:08:18,000
and able to well, get hold of any data returned

160
00:08:18,000 --> 00:08:20,000
by that formAction

161
00:08:20,000 --> 00:08:23,000
because this useFormState hook, then we'll make sure

162
00:08:23,000 --> 00:08:24,000
that any data returned

163
00:08:24,000 --> 00:08:28,000
by your formAction will be set up as a new state.

164
00:08:29,000 --> 00:08:32,000
That's why you get back a new formAction

165
00:08:32,000 --> 00:08:35,000
to which React basically is listening to make sure

166
00:08:35,000 --> 00:08:37,000
that it is able to update that state.

167
00:08:38,000 --> 00:08:42,000
And therefore, it's now this updated formAction,

168
00:08:42,000 --> 00:08:45,000
which you should use as a value

169
00:08:45,000 --> 00:08:47,000
for the action prop of the form

170
00:08:47,000 --> 00:08:50,000
so that React is able to listen to the submission

171
00:08:50,000 --> 00:08:52,000
and update that form state.

172
00:08:53,000 --> 00:08:56,000
Now, with that, if you save that,

173
00:08:56,000 --> 00:08:57,000
you would get an error though

174
00:08:57,000 --> 00:09:01,000
that useFormState only works in a client component.

175
00:09:02,000 --> 00:09:06,000
Therefore, what you should do when using useFormState,

176
00:09:06,000 --> 00:09:11,000
you should add use client at the top of the file.

177
00:09:11,000 --> 00:09:14,000
So here at the top of this page.js file.

178
00:09:15,000 --> 00:09:18,000
With that, if you reload, you get another error though

179
00:09:18,000 --> 00:09:21,000
that we now also have some code that's decorated

180
00:09:21,000 --> 00:09:25,000
with use server inside of a client component,

181
00:09:25,000 --> 00:09:30,000
and that's not allowed, which kind of makes sense I guess

182
00:09:30,000 --> 00:09:34,000
because with use client at the top of this file,

183
00:09:34,000 --> 00:09:35,000
we're telling React

184
00:09:35,000 --> 00:09:37,000
that all the code in here should be executed

185
00:09:37,000 --> 00:09:41,000
on the client side, but then we got some code in there

186
00:09:41,000 --> 00:09:43,000
where we tell React and NextJS

187
00:09:43,000 --> 00:09:46,000
that it should only be executed on the server side,

188
00:09:46,000 --> 00:09:50,000
which are some clashing expectations.

189
00:09:50,000 --> 00:09:52,000
But we can easily work around that problem

190
00:09:52,000 --> 00:09:55,000
by just restructuring our code a bit.

