0

In a form that I am making the material that is being created in the form should have multiple width options that can be added. This means that I will have a text input where the user can add an option, and when this option is added, it should be added to the React Hook Form widthOptions array, without using the regular react state. How would one do this? How do you add an item to the total React Hook Form state, I only see options for just one input field corresponding to a property.

This is how i would do it using the regular React state

import { TrashIcon } from "@heroicons/react/24/outline";
import React, { useRef, useState } from "react";

const Test = () => {
  const [widthOptions, setWidthOptions] = useState<string[]>([]);
  const inputRef = useRef<HTMLInputElement>(null);
  const removeWidthOption = (widthOption: string) => {
    setWidthOptions(widthOptions.filter((option) => option !== widthOption));
  };

  const addWidthOption = (widthOption: string) => {
    setWidthOptions([...widthOptions, widthOption]);
  };

  const editWidthOptions = (widthOption: string, index: number) => {
    const newWidthOptions = [...widthOptions];
    newWidthOptions[index] = widthOption;
    setWidthOptions(newWidthOptions);
  };

  return (
    <div>
      <input type="text" ref={inputRef} />
      <button onClick={() => addWidthOption(inputRef?.current?.value)}>
        Add Width Option
      </button>
      {widthOptions.map((option, index) => (
        <div className="flex">
          <input
            type="text"
            value={option}
            onChange={() => editWidthOptions(option, index)}
          />
          <button type="button" onClick={() => removeWidthOption(option)}>
            <TrashIcon className="w-5 h-5 mb-3 text-gray-500" />
          </button>
        </div>
      ))}
    </div>
  );
};

export default Test;

1 Answer 1

1

You can just the controller component for this as for all other fields. Since you have not shared any of you code here is a generic multi-select

<Controller
  name={name}
  render={({ field: { value, onChange, ref } }) => {
    return (
    // You can use whatever component you want here, the you get the value from the form and use onChange to update the value as you would with a regular state
      <Test
        widthOptions={value}
        setWidthOptions={onChange}
      />
    );
  }}
/>;

https://react-hook-form.com/api/usecontroller/controller/

And in you Test component remove the state and get the props instead

const Test = ({widthOptions, setWidthOptions}) => {
const inputRef = useRef<HTMLInputElement>(null);
.
.
.
Sign up to request clarification or add additional context in comments.

4 Comments

Ok, and what needs to be done in the onChange? How do i refer to the state of the field / form?
React hook form hold the state, name acts as the key. onChange just take any value and set it as the new value of the name. This is basically the same as what I have in the example above onChange={(newArray: string[])=>onChange(newArray)} If you need further assistance you will have to updated your question with the code you need help with.
I have added an example of what i want, using regular React state
@Bowis great job on the component, I have updated my answer. As you can see you can just replace the state with props.

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.