
Join the Conversation!
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
"Please login to view comments"
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
Complete source code available till this point of lesson is available at
How did you manage to remove the blur property and reach here?
Upgrading gives you access to quizzes so you can test your knowledge, track progress, and improve your skills.
By logging in, you'll unlock full access to this and other free tutorials on JSM Pro.
Why? Logging in lets us personalize your learning experience, track your progress, and keep you in the loop with new workshops, coding tips, and platform updates.
You'll also be the first to know about upcoming launches, events, and exclusive discounts.
No spam—just helpful content to level up your skills.
If that sounds fair, go ahead and log in to continue →
Enter your name and email to get instant access
##Looks like we found a thief monkey By the way, I liked the trick how you reached till here. You have a good sense of humor. You will improve a lot if you join our course with this passion.
var
(function-scoped, outdated)let
(block-scoped, modern and recommended)const
(block-scoped, cannot be reassigned)_
, or $
let let = 5;
is invalid)myVar
and myvar
are different)string
, number
, boolean
, null
, undefined
, bigint
, symbol
Objects
, Arrays
, Functions
Subscribing gives you access to a brief, insightful summary of each lecture to stay on track.
00:00:02 To get started creating the ask a question page, let's click the ask a question button to navigate to it.
00:00:09 That's going to lead us to ask a question or ask question page right here in a root ask question.
00:00:16 But now we want to create a new client side component, which is going to be the question form, which we can import and use within the server side rendered
00:00:26 ask a question page.
00:00:27 So let's create a new component right here inside of Components and then Forms and call it QuestionForm.tsx.
00:00:37 Run RAFCE and import it within the Ask a Question page in a way that first will have an H1 right here at the top that's going to say Ask a Question And
00:00:50 we can give it a class name equal to H1 dash bold, text dash dark 100, light 900, and save it.
00:01:00 There we go.
00:01:01 That's already looking better.
00:01:03 We don't need to provide any styles to this div, so let's simply make it a ReactFragment.
00:01:08 And right within it, let's render a div with a class name equal to margin top of 9, to divide it a bit from the top.
00:01:17 And within it, render a question form.
00:01:21 Self-closing component.
00:01:22 That's it.
00:01:23 Now we can head over into the question form and start implementing it.
00:01:28 So let's ask ourselves, what kind of fields will we need to have within our question form?
00:01:34 So we can head over to create a question, which is right here.
00:01:38 Ask a public question.
00:01:40 First of all, we have a question title, then we have a detailed explanation of the problem, and then up to five tags that we can add for each one of the questions.
00:01:51 So before we actually go ahead and create the UI for the form, let's first write the validation by heading over to validations.ts where right now we have
00:02:01 the validation for the sign in and the sign up.
00:02:05 Now we can create a new one by running export const ask question schema equal to z.object to which we can pass the shape of a title equal to z.string and
00:02:23 you can see that already it autofills it for me.
00:02:26 So I will actually let it autofill it.
00:02:28 For the title, we have a Z dot string with a minimum of five and a maximum of 100 characters.
00:02:36 And then instead of body, let's call this content where we have a string with a minimum of one character, meaning that it is required.
00:02:44 And in this case, I don't even want to provide a max because sometimes coding questions can get long.
00:02:51 Finally, we need to have our tags, which are going to be equal to z.array of strings.
00:02:58 But for each string, we can actually provide some additional validations by saying it's going to be a min of one character,
00:03:06 saying tag is required.
00:03:08 And then another .max where we can say tag cannot exceed 30 characters.
00:03:13 And instead of saying that it should be non-empty, we can say that we can have a minimum of one tag, at least one tag is required.
00:03:20 And we can have a .max of 3. So we can say 3 tags is the maximum.
00:03:27 Cannot add more than 3 tags.
00:03:29 So now we have the validation for our question form, which we can use right here.
00:03:34 I know that we have already set a couple of Schatzian forms, but I want to guide you to do this one more time from scratch so you truly understand how
00:03:42 creating forms in Schatzian using Zod validation and the React hook form works.
00:03:47 First things first, we need to create a new form by saying const form is equal to use form coming from React hook form.
00:03:56 To it, we need to pass a resolver, which resolves to a specific schema.
00:04:01 So we can say dot resolver coming from hook form.
00:04:04 And to it, we need to pass the schema we created, ask question schema.
00:04:09 And the second part is going to contain the default values for this specific form.
00:04:14 which in this case will be a title of an empty string.
00:04:17 It'll be content of an empty string and finally tags of an empty array.
00:04:22 And now you can see we have our form, which we can then use within the UI.
00:04:26 So let's actually create a new form and make sure that this is a UI form.
00:04:32 So coming from Shazian components and not React hook form.
00:04:36 Okay.
00:04:37 So check the import and make sure it is that that slash UI forward slash form.
00:04:41 And to this form, you need to spread the form component that we created right above.
00:04:46 Then within it, we can create a regular HTML form, give it a class name equal to flex w dash full flex dash call, and a gap of 10 in between the elements.
00:05:01 Now, it seems that we have a problem saying that useForm coming from react-hookform doesn't exist.
00:05:07 Even though if we go into it, we can see that it is indeed exporting it right here.
00:05:12 I think the issue is happening because we haven't added a use client directive at the top.
00:05:17 If you save it, you'll see that now it's fixed.
00:05:21 I do agree that this is slightly problematic because the initial error is misleading, but it cannot get the correct use form hook because we haven't added
00:05:31 the use client here.
00:05:33 So sometimes you might be careful that it's not just the use states or the built-in hooks that you can use that require you to transform something into
00:05:42 use client component.
00:05:44 Sometimes it's third-party libraries like react hook form.
00:05:48 So once we switch it to use client, it works.
00:05:51 Now let's continue with the form.
00:05:53 I'll give it an onSubmit handler.
00:05:55 So what's going to happen once we submit and you can just say form.handleSubmit and then you pass in the function that you want to run when you submit it.
00:06:04 I'll call it handle.
00:06:07 create question because that's exactly what we want to do.
00:06:12 Create a question once we submit the form.
00:06:15 So I'll define this const handle create question, which is going to be a empty callback function for now.
00:06:23 There we go.
00:06:24 No complaints so far.
00:06:26 Now let's head over to inside of the form and let's create the first form field.
00:06:32 In this case, I actually want to head over to some of our previous forms like the odd form, just to copy a form field because they're mostly the same.
00:06:40 So I'll copy the entire form field in this case, all the way from the start to the self-closing tag.
00:06:47 and I'll paste it right here within the form.
00:06:50 Now of course we'll style it to make sense in this case.
00:06:53 We have a form field which we have to import from UI form.
00:06:57 The key we don't need because we're not mapping over these.
00:07:01 The name in this case will actually be just the title which is going to be a static title string because first we want to have the title of the question.
00:07:10 Then, we want to render a form item, and this form item will have a flex, wfull, and flex call.
00:07:18 No need to provide a gap in this case.
00:07:21 After that, we have a form label, which we can also import, which is going to have a paragraph, semi-bold, text-dark 400, light 800. And within it,
00:07:33 we don't have to do any sort of logic.
00:07:35 We can simply say question title, and then we can render a span that's going to just render the asterisk, meaning it's mandatory to enter this field.
00:07:45 I'll give it a class name of text-primary-500.
00:07:49 So now if we save it, it's still going to be broken because we have to fix the import.
00:07:54 So let's import the input.
00:07:56 We have to do it at the top by saying import input, not from post CSS.
00:08:00 That was a mistake.
00:08:01 It has to come from UI input.
00:08:03 We can remove the required and the type.
00:08:06 We're going to spread the field.
00:08:08 But before we do, we can fix these class names.
00:08:12 It's gonna be paragraph regular, it's gonna have a no focus, with a background light 700, dark 300, light border 2, text dark 300, light 700, min-h of 56 pixels,
00:08:29 so we can manually type 56 pixels right here.
00:08:32 No need to give it rounded in this case, and we can give it border.
00:08:35 And this is how that input looks like.
00:08:37 Great.
00:08:38 Right below the input and below the form control, in this case, we can add a form description.
00:08:44 So let's say form description coming from UI form, and it's going to have a class name equal to body-regular, text-light-500,
00:08:56 and the margin top of 2.5. Within it, we can render some kind of information for this field.
00:09:03 Be specific and imagine You're asking a question to another person.
00:09:12 There we go.
00:09:13 And now what we can do is we can duplicate this field two more times.
00:09:17 So one and two.
00:09:20 And now we can fix them for each one of these.
00:09:23 The second form field will not be a title.
00:09:25 It'll be content.
00:09:27 So we can change the label to say detailed explanation of your problem.
00:09:34 like this then inside of here we won't render the regular input rather we'll render the editor component which will allow us to in detail specify the problem
00:09:45 that we have with some code blocks and more we can also fix the description to say something like introduce the problem and expand on what you've put in
00:09:57 the title and save okay that's great soon enough we'll add a real editor right here and then for the last one we'll have a name equal to tags where we'll
00:10:07 render a form item and in this case we can give it a gap of three in between the elements where we're gonna render a form label with a title of tags And
00:10:18 within it, within the form control, we'll want to render a div.
00:10:22 And then within the form control, we can render a div.
00:10:25 We can put this input within a div and give it a placeholder equal to add tags.
00:10:33 And then below it, we'll want to map over the tags that were created and show them right here.
00:10:38 So I'll simply say tags.
00:10:41 Of course, this part will come later.
00:10:43 And we can also modify the description by saying something like, add up to three tags to describe what your question is about.
00:10:54 You need to press enter to add a tag.
00:10:58 Okay, great.
00:11:01 Finally, going below this entire input, we can render a div that'll have a class name equal to margin top of 16 flex and justify end.
00:11:13 And here we can simply render a submit button coming from UI buttons with a type equal to submit.
00:11:22 A class name of primary dash gradient and exclamation mark, text dash light dash 900 and w dash fit.
00:11:32 Within it, we can say ask question.
00:11:37 There we go.
00:11:37 So now we have a beautiful button, ask a question right here at the bottom right.
00:11:41 It seems like we have some warnings and you'll see those warnings are because this field is not used right here in the form field.
00:11:48 We also have some warnings because the quote string is not escaped.
00:11:52 So it gives you right here the code that you need to use to escape that quote string.
00:11:56 So I'll just write like this.
00:11:59 Same thing here.
00:12:01 And I think that's it.
00:12:03 We don't have any more.
00:12:04 You can see that it still has the quote, but now it's not complaining.
00:12:10 And with that in mind, the UI of the question form is looking great, as you can see here.
00:12:15 But now we have to dive into creating a detailed editor that will allow us to bold, italicize, or provide headings, or quote different things,
00:12:24 or even put hyperlinks and blocks of code so we can explain our bug more properly so people can provide us with a better solution.
00:12:33 And let me just tell you that we will reuse this editor also when providing different answers, so that way people that provide answers will be able to
00:12:42 help us in a more seamless way.
00:12:43 So let me commit this right here by saying, implement the UI of the question form, commit and sync.
00:12:53 And next we can focus on implementing the MDX editor.