Neeshツ
Neeshツ
TTCTheo's Typesafe Cult
Created by Neeshツ on 2/12/2024 in #questions
Next.js Client Side Conditional State
I have a Next.js app with a client side part of the app. The form takes a min and max from the user. Using that, I render a form with (max - min) inputs. I validate the input for the max and min to make sure the (max - min) always returns a positive number. To render the form, I create a type using numberOfQuestions and create a React State.
const questionsSchema = numericEnum(Options)
.optional()
.array()
.length(numberOfQuestions)
const defaultState: z.infer<typeof questionsSchema> = Array(
numberOfQuestions,
).map((_) => undefined)
const [answers, setAnswers] =
useState<z.infer<typeof questionsSchema>>(defaultState)
const questionsSchema = numericEnum(Options)
.optional()
.array()
.length(numberOfQuestions)
const defaultState: z.infer<typeof questionsSchema> = Array(
numberOfQuestions,
).map((_) => undefined)
const [answers, setAnswers] =
useState<z.infer<typeof questionsSchema>>(defaultState)
This works fine in dev since previous validation makes sure the numbeOfQuestions is never NaN. However, when I try to next build, I guess next tries to run it and numberOfQuestions is NaN giving me an RangeError: Invalid array length. So now I decided return before this ^ if numberOfQuestions is NaN
if (typeof numberOfQuestions !== "number") {
return (
<div>
<p>Error: Max questions not greater than min questions.</p>
</div>
)
}
if (typeof numberOfQuestions !== "number") {
return (
<div>
<p>Error: Max questions not greater than min questions.</p>
</div>
)
}
However, this means I'm "conditionally setting state" which is not allowed. React Hook "useState" is called conditionally. React Hooks must be called in the exact same order in every component render. Did you accidentally call a React Hook after an early return?eslintreact-hooks/rules-of-hooks https://reactjs.org/docs/hooks-rules.html Any ideas on how I can fix this?
2 replies
TTCTheo's Typesafe Cult
Created by Neeshツ on 2/7/2024 in #questions
React Hook Form x Zod - Dynamic Schema Object
I'm trying to make an app which helps you practice for Multiple Choice Questions. In the settings page, you add the start number and end number for questions for example: Starts 1, Ends 20. It should then create 20 questions labelled 1, 2, 3...20. I'm using react-hook-form with zod for validation. How can I architect the schema for this? The schema should dynamically have the number of questions and an option between 1-4 as the value. Initially I thought the schema can be an array of an enum (1-4) of a specific length. But since the schema is not an object with keys, I don't have type completion on the name field of the form inputs. My second idea was to make the schema an object with keys q1, q2 ... q20 with every value as the enum (1-4). This would allow me to make the input names q1, q2, etc. However idk how to create this schema object. I have to somehow iterate over an Array(numberOfQuestions) and append entries to the z.object({}) 2 questions: Is ^ this an appropriate solution? If not, what would you suggest. If yes, how would I go about creating a schema z.object({}) with dynamic entries This is what I started with, however, typing this is a nightmare.
let questionsObject
Array(numberOfQuestions).map(
({ _, i }) => (questionsObject[`q${i}`] = z.enum(["1", "2", "3", "4"])),
)
const questionsSchema = z.object(questionsObject)
let questionsObject
Array(numberOfQuestions).map(
({ _, i }) => (questionsObject[`q${i}`] = z.enum(["1", "2", "3", "4"])),
)
const questionsSchema = z.object(questionsObject)
Any suggestions or discussion is welcome
7 replies
TTCTheo's Typesafe Cult
Created by Neeshツ on 7/28/2023 in #questions
How to correctly type an async Server Component in Next.js
I have a component in my Next.js project that uses async code to fetch data.
const H2: FC<HTMLAttributes<HTMLHeadingElement>> = ({
className,
...props
}) => {}
const H2: FC<HTMLAttributes<HTMLHeadingElement>> = ({
className,
...props
}) => {}
This was the code before and the type was working. Now I want to make this function async like so
const H2: FC<HTMLAttributes<HTMLHeadingElement>> = async ({
className,
...props
}) => {
const H2: FC<HTMLAttributes<HTMLHeadingElement>> = async ({
className,
...props
}) => {
Simply wrapping the FC type in a Promise<> doesn't work. I am not very well versed in complex Generics and how they work with Promises. How can I type this function correctly?
4 replies