Florestan Korp
Florestan Korp

Reputation: 709

React Hooks Form not returning values on submit

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

Answers (1)

GBourke
GBourke

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

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

Upvotes: 4

Related Questions