0
votes

I'm using Material UI Select as a reusable component, and I want to validate it with react-hook-form by passing props from parent to child component. So far, I've tried to use from RHF, and to pass some props to the child, but somehow error wont disappear when I select option. This is my code

import React from 'react';
import styled from '@emotion/styled';
import { Select, MenuItem } from '@material-ui/core';
import { ASSelect } from '../../ASSelect';
import { Controller, useForm } from 'react-hook-form';

const { register, handleSubmit, watch, errors, control, setValue } = useForm();
  const onSubmit = (data: any) => {
    console.log(errors);
  };
  
const defaultDashboard = [
  { value: 'chocolate', label: 'Chocolate' },
  { value: 'strawberry', label: 'Strawberry' },
  { value: 'vanilla', label: 'Vanilla' },
];
  
const Parent = () => {
  return (
    <Controller
          as={
            <ASSelect
              menuItems={defaultDashboard}
              label="Default dashboard*"
              handleChange={dashboardHandler}
              value={dashboardValue}
          }
          name="Select"
          control={control}
          rules={{ required: true }}
          onChange={([selected]) => {
            return { value: selected };
          }}
        />
        {errors.Select ? <span>Default dashboard is required</span> : null}
    )
 }

export {Parent};

const ASSelect = ({menuItems, label, handleChange, value}) => {
  return (
    <div>
      <Select>
      {menuItems.map((el, index)=> {
        return <MenuItem key={index}>{el.label}</MenuItem>
      }}
    </Select>
    </div>
  )}
  
 export {ASSelect};
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

So when I submit a form without selecting anything, the error will popup. But when I select an option, the error will remain there. What am I doing wrong?

1

1 Answers

2
votes

You can use Select with Controller from react-hook-forms in the following way:

const SelectController = ({ name, menuItems, control }) => (
  <Controller
    as={
      <Select>
        {menuItems.map(({ value, label }, index) => (
          <MenuItem key={index} value={value}>
            {label}
          </MenuItem>
        ))}
        }
      </Select>
    }
    name={name}
    control={control}
    defaultValue=""
    rules={{ required: true }}
  />
);

or use Select with setValue from react-hook-forms as follows:

const SelectSetValue = ({ name, menuItems, setValue }) => {
  return (
    <Select
      name={name}
      defaultValue=""
      onChange={e => setValue(name, e.target.value)}
    >
      {menuItems.map(({ value, label }, index) => (
        <MenuItem key={index} value={value}>
          {label}
        </MenuItem>
      ))}
      }
    </Select>
  );
};

In both cases you get error-validation initially onSubmit event. Error display is updated afterwards for SelectController when you select a value and for SelectSetValue when you select a value and re-trigger onSubmit.

You can check a working example at following the link:
https://codesandbox.io/s/somaterialselecthookform-kdext?file=/src/App.js