Semantic-Org / Semantic-UI-React

The official Semantic-UI-React integration
https://react.semantic-ui.com
MIT License
13.21k stars 4.05k forks source link

Unable to get value of Dropdown with React Hook Form #4423

Closed sholladay closed 1 year ago

sholladay commented 1 year ago

Bug Report

I am trying out the beta for SUIR v4. Very excited about this because of the new ref forwarding, which means I can use React Hook Form with uncontrolled form components, leading to much simpler code. It is working great for the most part. Unfortunately, Dropdown still doesn't seem to be compatible with RHF when uncontrolled.

Steps

  1. Visit the sandbox
  2. Fill in both form fields with any value
  3. Submit the form

Expected Result

The form should submit successfully, with no errors, because both fields have a value.

Actual Result

While the text input succeeds, the dropdown fails the required validation and shows an error, even though a value is selected.

I am pretty sure this has something to do with the onChange and/or onBlur event handlers, because when I turn validation off and just log what RHF thinks the value of the dropdown is, it's always an empty string.

Version

4.0.0-beta.0

Testcase

https://codesandbox.io/s/react-hook-form-with-ui-library-forked-jpiwm2

ShaikEsub commented 1 year ago

May I work on this issue ?

levithomason commented 1 year ago

(Co-authored with ChatGPT, I tested the sandbox and it works...)

The problem is that the Form.Select component doesn't directly support the ref prop, so you can't just use the register function from react-hook-form to register it. However, react-hook-form provides the Controller component for this.

Modify the Form.Select part of your SetupForm function to use Controller. This will ensure that the select input is correctly registered with react-hook-form and its value is properly managed.

import { Controller } from 'react-hook-form';

// ...

const SetupForm = () => {
    const {
        formState: { errors, isSubmitting },
        handleSubmit,
        control  // <-- control is a method from react-hook-form
    } = useForm({ mode: 'onTouched' });

    // ...

    return (
        <Form onSubmit={handleSubmit(onSubmit)}>
            <Form.Input
                {...register('displayName', {
                    required: 'Please choose a display name'
                })}
                error={errors.displayName?.message}
                id="displayName"
                label="Display name"
                placeholder="John Doe"
            />

            <Controller
                control={control}
                name="favoriteColor"
                rules={{ required: 'Please choose a color' }}
                render={({ field }) => (
                    <Form.Select
                        {...field}
                        search
                        error={errors.favoriteColor?.message}
                        id="favoriteColor"
                        label="Favorite Color"
                        options={colors}
                        placeholder="Red"
                        onChange={(e, data) => field.onChange(data.value)}
                        onBlur={field.onBlur}
                    />
                )}
            />

            <Form.Button
                content="Finish setup"
                disabled={isSubmitting}
                loading={isSubmitting}
                type="submit"
            />
        </Form>
    );
};

// ...

The Controller component acts as a bridge between the Form.Select and react-hook-form. Notice that we're using the field.onChange and field.onBlur functions provided by Controller to manually handle the onChange and onBlur events. This ensures that the value selected in the dropdown is correctly registered with react-hook-form.

Please replace the original Form.Select part with the updated code and see if it resolves the issue.


Very curious if this both explains and solves your issue...

sholladay commented 1 year ago

We have always been able to use controlled form components and that does still work. But I thought SUIR v4 was going to make that unnecessary via ref forwarding. Are you saying that even with v4 we will still need to use a controlled dropdown? That is unfortunate if so.

layershifter commented 1 year ago

We have always been able to use controlled form components and that does still work. But I thought SUIR v4 was going to make that unnecessary via ref forwarding. Are you saying that even with v4 we will still need to use a controlled dropdown?

Yep, it will be still a thing as Dropdown does not implement a native select (it's too complex for it).

sholladay commented 1 year ago

Thank you for clarifying. So this behavior is WAI. I'll close this.