'How to handle Material UI inputs with React-hook-form?

I'm working on a dynamic form where you can add and remove fields at will using React-hook-form. For this I made a table component where the input will be held. This is how it looks.

import {useFieldArray, useFormContext, Controller} from "react-hook-form";
import {cloneElement} from "react";
import {IoMdAdd, IoMdRemoveCircle} from "react-icons/io";

interface TableData {
    tableName:string,
    inputFields: {
        title: string,
        name: string,
        inputComponent: React.ReactElement, // Did this since input can be text, select, or entire component
    }[],
    inputBlueprint: object,
    min?: number
};

const InputTable = ({tableName, inputFields, inputBlueprint, min}: TableData) => {
    const {fields, remove, append} = useFieldArray({name: tableName});
    const {register, formState: {errors}, control} = useFormContext();
    
    return (
        <table className="table-auto border-collapse block m-auto w-fit max-w-xs max-h-48 overflow-auto sm:max-w-none my-3">
            <thead className="text-center">
                <tr>
                    {inputFields.map((input) => (
                        <td className="border-2 border-gray-400 px-5" key={input.title}>{input.title}</td>
                    ))}
                </tr>
            </thead>

            <tbody>
                {fields.map((field, index) => (
                    <tr key={field.id}>
                        {inputFields.map((input) => (
                            <td key={input.title} className="border-gray-400 border-2 p-0">
                                {input.inputComponent.type === "input" && cloneElement(input.inputComponent, {
                                    className: "bg-transparent outline-none block w-full focus:bg-gray-400 dark:focus:bg-gray-500 p-1",
                                    ...register(`${tableName}.${index}.${input.name}` as const)
                                    })
                                }
                                {input.inputComponent.type !== "input" && //This doesn't work at all
                                    <Controller
                                    name={`${tableName}.${index}.${input.name}`}
                                    control={control}
                                    defaultValue=""
                                    render={({field: {onChange, value}}) => {return input.inputComponent}}
                                    />
                                }
                                {errors[tableName]?.[index]?.[input.name] && 
                                <p className="bg-red-400 p-1">
                                    {errors[tableName][index][input.name]?.message}
                                </p>
                                }
                            </td>
                        ))}
                        {(min === undefined || min <= index) && 
                            <td onClick={() => remove(index)}><IoMdRemoveCircle className="text-red-600 text-2xl"/></td>
                        }
                    </tr>
                ))}
                <tr>
                    <td onClick={() => append(inputBlueprint)} className="bg-green-500 border-gray-400 border-2" 
                    colSpan={inputFields.length}>
                        <IoMdAdd className="m-auto"/>
                    </td>
                </tr>
                {errors[tableName] && 
                <tr>
                    <td className="max-w-fit text-center">
                        {errors[tableName].message}
                    </td>
                </tr>}
            </tbody>
        </table>
    )
}

export default InputTable

It works for the most part with regular inputs (html input and select) but I'm having problems since I'm using Material's UI Autocomplete component for suggestions in some fields and since React-hook-form uses unregistered components and MUI uses registered, they really clash. Is there a better way to do this? I have thought about using the children prop but I'm not entirely sure if this would better the situation.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source