1
00:00:00,000 --> 00:00:03,000
So how can we handle validation errors

2
00:00:03,000 --> 00:00:05,000
like this in a more elegant way?

3
00:00:07,000 --> 00:00:10,000
Well, in Server Actions, as we have it here,

4
00:00:10,000 --> 00:00:15,000
you are not limited to redirecting or throwing errors.

5
00:00:15,000 --> 00:00:19,000
Instead, you can also return values.

6
00:00:19,000 --> 00:00:23,000
You can return response objects to be precise

7
00:00:25,000 --> 00:00:26,000
and I'll show you how

8
00:00:26,000 --> 00:00:30,000
to access those objects in your components in just a second.

9
00:00:31,000 --> 00:00:34,000
So here we could return an object

10
00:00:34,000 --> 00:00:37,000
which maybe has a message field which holds a value

11
00:00:37,000 --> 00:00:38,000
of invalid input.

12
00:00:39,000 --> 00:00:42,000
Though the shape of this object is totally up to you,

13
00:00:42,000 --> 00:00:46,000
it's just important that it's a serializable object,

14
00:00:46,000 --> 00:00:50,000
which means it, for example, shouldn't include any methods

15
00:00:50,000 --> 00:00:52,000
because those would get lost whilst

16
00:00:52,000 --> 00:00:54,000
being sent to the client.

17
00:00:55,000 --> 00:00:58,000
But any simple values like strings, numbers,

18
00:00:58,000 --> 00:01:03,000
nested objects or nested arrays, those values all work.

19
00:01:04,000 --> 00:01:07,000
So that's how we can return a response.

20
00:01:08,000 --> 00:01:12,000
How can we then use that response in that share page

21
00:01:12,000 --> 00:01:14,000
where we trigger that Server Action?

22
00:01:16,000 --> 00:01:20,000
Well, we can use it with help of another hook, another hook

23
00:01:20,000 --> 00:01:25,000
provided by React dom, the useFormState hook.

24
00:01:26,000 --> 00:01:30,000
So not useFormStatus, which we had before, but useFormState.

25
00:01:32,000 --> 00:01:34,000
Sounds similar but is a different hook.

26
00:01:35,000 --> 00:01:38,000
This hook also must be imported

27
00:01:38,000 --> 00:01:41,000
from React dom like this.

28
00:01:43,000 --> 00:01:47,000
And then this hook here works a little bit

29
00:01:47,000 --> 00:01:51,000
like the useState hook that's built into React

30
00:01:51,000 --> 00:01:56,000
because this hook is responsible for managing the state

31
00:01:56,000 --> 00:02:00,000
of this page or of this component, which uses a forum

32
00:02:00,000 --> 00:02:03,000
that will be submitted with help of Server Actions.

33
00:02:03,000 --> 00:02:06,000
And that's precisely the use case

34
00:02:06,000 --> 00:02:08,000
where useFormState can help you

35
00:02:08,000 --> 00:02:11,000
because useFormState needs two arguments.

36
00:02:11,000 --> 00:02:15,000
And the first argument is the actual Server Action

37
00:02:15,000 --> 00:02:18,000
that should be triggered when the form is submitted,

38
00:02:18,000 --> 00:02:20,000
in this case shareMeal.

39
00:02:22,000 --> 00:02:24,000
The second argument you pass

40
00:02:24,000 --> 00:02:29,000
to useFormState is the initial state of this component,

41
00:02:29,000 --> 00:02:33,000
and that simply means the initial value

42
00:02:33,000 --> 00:02:35,000
that should be returned by useFormState

43
00:02:35,000 --> 00:02:38,000
before this action has been triggered

44
00:02:38,000 --> 00:02:41,000
and yielded a response.

45
00:02:41,000 --> 00:02:42,000
So the initial value

46
00:02:42,000 --> 00:02:45,000
that should be used if we haven't received a response

47
00:02:45,000 --> 00:02:49,000
from this action yet, and that could be anything you want,

48
00:02:49,000 --> 00:02:50,000
for example, null

49
00:02:50,000 --> 00:02:53,000
or an object where you have a message field

50
00:02:53,000 --> 00:02:56,000
that holds a value of null.

51
00:02:56,000 --> 00:03:00,000
To reassemble the shape of that response,

52
00:03:00,000 --> 00:03:02,000
we will eventually send back.

53
00:03:03,000 --> 00:03:06,000
Eventually I'll send back an object with this shape

54
00:03:06,000 --> 00:03:07,000
where the message holds a string.

55
00:03:07,000 --> 00:03:11,000
So our initial value here could be the same shape

56
00:03:11,000 --> 00:03:13,000
but null as a value for the message.

57
00:03:15,000 --> 00:03:18,000
Then useFormState will give you an array

58
00:03:18,000 --> 00:03:22,000
with exactly two elements, which might sound familiar

59
00:03:22,000 --> 00:03:25,000
because the default useState hook

60
00:03:25,000 --> 00:03:28,000
provided by React also gives you two elements.

61
00:03:29,000 --> 00:03:32,000
And indeed here the two elements we get here are kind

62
00:03:32,000 --> 00:03:37,000
of similar to the two elements we get from useState

63
00:03:37,000 --> 00:03:41,000
because we get the current state, the current

64
00:03:41,000 --> 00:03:45,000
response you could say, of this page here,

65
00:03:45,000 --> 00:03:47,000
of this component here.

66
00:03:47,000 --> 00:03:49,000
So the latest response returned

67
00:03:49,000 --> 00:03:52,000
by this Server Action in the end

68
00:03:52,000 --> 00:03:56,000
or this initial state if no response has been received yet.

69
00:03:58,000 --> 00:04:01,000
And we get another formAction here,

70
00:04:01,000 --> 00:04:03,000
which we should actually set as a value

71
00:04:03,000 --> 00:04:06,000
for this action prop on the form now.

72
00:04:07,000 --> 00:04:10,000
So instead of setting share meal as a value

73
00:04:10,000 --> 00:04:14,000
for action down here, I'm now setting this formAction,

74
00:04:14,000 --> 00:04:17,000
which I'm getting back from useFormState as a value

75
00:04:17,000 --> 00:04:19,000
for the action down there.

76
00:04:21,000 --> 00:04:23,000
And this must be done so

77
00:04:23,000 --> 00:04:26,000
that useFormState can basically step in

78
00:04:26,000 --> 00:04:29,000
and manage that state for this component.

79
00:04:29,000 --> 00:04:32,000
And that state depends on the execution

80
00:04:32,000 --> 00:04:35,000
of that Server Action and its response.

81
00:04:35,000 --> 00:04:38,000
And that's why useFormState kind of needs to act

82
00:04:38,000 --> 00:04:40,000
as a man in the middle, you could say.

83
00:04:41,000 --> 00:04:44,000
With that, we can then use this state here,

84
00:04:44,000 --> 00:04:46,000
which will essentially be either this year

85
00:04:46,000 --> 00:04:49,000
or any response we got back from ShareMeal

86
00:04:49,000 --> 00:04:53,000
to output data in this component.

87
00:04:54,000 --> 00:04:57,000
Now, in this case, I know that state will

88
00:04:57,000 --> 00:05:01,000
therefore either be an object with a message that's a string

89
00:05:02,000 --> 00:05:06,000
or it'll be an object with a message that's null.

90
00:05:07,000 --> 00:05:11,000
So we can use it down here at the end of the form right

91
00:05:11,000 --> 00:05:13,000
before the submit button, let's say,

92
00:05:13,000 --> 00:05:16,000
to output an error message.

93
00:05:18,000 --> 00:05:22,000
For that, we can check if state.message is truthy,

94
00:05:23,000 --> 00:05:25,000
which means we have a message.

95
00:05:25,000 --> 00:05:28,000
And in that case I wanna output it here

96
00:05:28,000 --> 00:05:30,000
between my paragraph tags.

97
00:05:32,000 --> 00:05:34,000
Now with that, we also need

98
00:05:34,000 --> 00:05:37,000
to tweak the shareMeal action though,

99
00:05:37,000 --> 00:05:41,000
because when passing it as a value to useFormState,

100
00:05:41,000 --> 00:05:44,000
it must have a different shape than it did before.

101
00:05:45,000 --> 00:05:49,000
It should no longer just accept that form data.

102
00:05:49,000 --> 00:05:53,000
Instead, it should now actually accept two parameters

103
00:05:53,000 --> 00:05:56,000
because useFormState will pass two parameters

104
00:05:56,000 --> 00:05:59,000
to shareMeal when it executes it when the

105
00:05:59,000 --> 00:06:00,000
form gets submitted.

106
00:06:01,000 --> 00:06:05,000
The second parameter will still be that submitted data,

107
00:06:05,000 --> 00:06:08,000
but the first parameter will be the previous state.

108
00:06:09,000 --> 00:06:12,000
So either that initial state that we set up here

109
00:06:12,000 --> 00:06:15,000
or any other previous responses

110
00:06:15,000 --> 00:06:19,000
that might have been generated, I don't care about it here,

111
00:06:19,000 --> 00:06:21,000
but still we need to accept it

112
00:06:21,000 --> 00:06:23,000
because form data is now the second argument

113
00:06:23,000 --> 00:06:25,000
we get, not the first.

114
00:06:28,000 --> 00:06:30,000
With that though, we got everything set up that needs

115
00:06:30,000 --> 00:06:34,000
to be set up, but we'll now get an error if we try

116
00:06:34,000 --> 00:06:39,000
to load the page because useFormState, since it in the end

117
00:06:39,000 --> 00:06:42,000
again deals with updating the client, needs

118
00:06:42,000 --> 00:06:47,000
to be executed in a client component and therefore

119
00:06:47,000 --> 00:06:50,000
we should add use client here

120
00:06:50,000 --> 00:06:53,000
in our shareMeal page component file.

121
00:06:55,000 --> 00:06:58,000
We could again try to outsource this into some nested

122
00:06:58,000 --> 00:07:01,000
component, but here I'll stick to this component,

123
00:07:01,000 --> 00:07:04,000
add use client and save that.

124
00:07:05,000 --> 00:07:07,000
And with that, this is looking good.

125
00:07:07,000 --> 00:07:09,000
We got no error and

126
00:07:09,000 --> 00:07:13,000
therefore now we can try submitting an invalid form again.

127
00:07:13,000 --> 00:07:17,000
So here, I'll enter some data like this

128
00:07:18,000 --> 00:07:21,000
and if I now inspect my email field

129
00:07:21,000 --> 00:07:25,000
and I remove the required prop here

130
00:07:25,000 --> 00:07:30,000
and I click share meal, I now get this error message.

131
00:07:32,000 --> 00:07:35,000
Now of course we could make it pop more.

132
00:07:35,000 --> 00:07:37,000
We could make sure that it stands out,

133
00:07:37,000 --> 00:07:42,000
that it's more descriptive and you can do all these things.

134
00:07:42,000 --> 00:07:44,000
You can, for example, tweak that message here,

135
00:07:44,000 --> 00:07:46,000
which in the end is the message

136
00:07:46,000 --> 00:07:48,000
that's showing up on the screen.

137
00:07:48,000 --> 00:07:51,000
But the main takeaway is that this is

138
00:07:51,000 --> 00:07:54,000
how you can show such an error message,

139
00:07:54,000 --> 00:07:58,000
that you can return responses in your Server Actions

140
00:07:58,000 --> 00:08:00,000
and that you can get

141
00:08:00,000 --> 00:08:03,000
and handle them with help of the useFormState hook.

