2

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>
  );
}

1 Answer 1

4

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

  1. Ensure you add a "key" attribute on the Question component when you map the QUESTIONS array
  2. pass register as a prop to Question, and use it as 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

EDIT

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 })} />
Sign up to request clarification or add additional context in comments.

4 Comments

If you are using react-hook-forms 7.0.0 + you need to use register in a different way as explained in this answer
thanks, I have added the comment with reference to the answer.
Awesome and Thank you for pointing out the correct path in solving the error for this question. It saved my day :)
If you're using the Controller component there is no need to register.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.