Reputation: 709
I want to build a form where I loop over an array of questions and collect the values of radio buttons for a quiz. Later I want to store those values, so I can can perform some calculations on the result, but for now I just want to log the value (1,2,3,4) and the name of the input to the console. As I'm new to React and Hooks, I have tried the following, but the result that is logged is always an epmty object. The desired result should look like this (built in vanilla JS):
https://florestankorp.github.io/D-D-AlignmentTest/
App.tsx
import React from 'react';
import { useForm } from 'react-hook-form';
import { Question } from '../shared/interfaces';
const QUESTIONS: Question[] = [
{
id: 'q201',
question:
'1. Family elders are expressing disapproval of you to the rest of the family. Do you:',
option1: 'Accept the criticism and change your ways?',
option2: 'Seek a compromise with them?',
option3:
'Besmirch the reputation of those expressing disapproval as you ignore their scorn?',
option4: 'Silence them any way you can?',
},
];
export default function App() {
const { register, handleSubmit } = useForm();
const onSubmit = (data: any) => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
{QUESTIONS.map((question) => (
<Question {...question} />
))}
<input type="submit" />
</form>
);
}
function Question(props: any): any {
return (
<div>
<p className="question">{props.question}</p>
<div>
<input name={props.id} value="1" type="radio" />
<label htmlFor={props.id}>{props.option1}</label>
</div>
<div>
<input name={props.id} value="2" type="radio" />
<label htmlFor={props.id}>{props.option2}</label>
</div>
<div>
<input name={props.id} value="3" type="radio" />
<label htmlFor={props.id}>{props.option3}</label>
</div>
<div>
<input name={props.id} value="4" type="radio" />
<label htmlFor={props.id}>{props.option4}</label>
</div>
</div>
);
}
Upvotes: 2
Views: 11870
Reputation: 1963
I see you are using the useForm hook. Looking at the docs, they provide a method called "register" which you use to register each input component with the hook. That needs to be incorporated into your Question component. I would suggest
ref={props.register}
on every input component.see below
export default function App() {
const { register, handleSubmit } = useForm();
const onSubmit = (data: any) => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
{QUESTIONS.map((question) => (
<Question {...question} register={register} key={question.id} /> //<-- notice register and key attribute
))}
<input type="submit" />
</form>
);
}
now you can include this prop in your question component
function Question(props: any): any {
return (
<div>
<p className="question">{props.question}</p>
<div>
<input name={props.id} value="1" type="radio" ref={props.register} /> //<-- note ref={props.register}
<label htmlFor={props.id}>{props.option1}</label>
</div>
<div>
<input name={props.id} value="2" type="radio" ref={props.register} />
<label htmlFor={props.id}>{props.option2}</label>
</div>
<div>
<input name={props.id} value="3" type="radio" ref={props.register} />
<label htmlFor={props.id}>{props.option3}</label>
</div>
<div>
<input name={props.id} value="4" type="radio" ref={props.register} />
<label htmlFor={props.id}>{props.option4}</label>
</div>
</div>
);
}
This should then update the state for the submit event. See this CodeSandbox
Added the Answer of @Amit from the comment added below
react-hook-form updated to 7.0.0 from 6.X.X and has breaking changes:
You have to replace all
ref={register}
with{...register('value_name')}
Example: Version 6.X.X:
<input ref={register({ required: true })} name="test" />
Version 7.0.X:
<input {...register('test', { required: true })} />
Upvotes: 4