feat(form): Add controlled mode to Select component
Refactors the `Select` component to support being used as a controlled component by accepting a `value` prop. This allows its state to be managed externally, for example, by React Hook Form. This change was necessary to properly implement the `clearable` functionality within forms. Previously, clearing the select would only update its internal state, not the form's state. - Added `value` and `useEffect` to sync with external state. - Updated the `onClear` handler to propagate the change via `onChange`. - Modified `AdminListFilters` to use the `Select` component in a controlled manner, passing `watch` and `setValue` from React Hook Form. - Adjusted the filter layout to be more responsive.
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
import { ChevronUpIcon } from "@/assets/icons";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { ILabelValue } from "@/types/shared";
|
||||
import { useId, useState, type ChangeEvent } from "react";
|
||||
import { useEffect, useId, useState, type ChangeEvent } from "react";
|
||||
import {
|
||||
type FieldErrors,
|
||||
type FieldValues,
|
||||
@@ -24,8 +24,9 @@ type PropsType<T extends FieldValues> = {
|
||||
required?: boolean;
|
||||
clearable?: boolean;
|
||||
onClear?: () => void;
|
||||
value?: string;
|
||||
} & (
|
||||
| { placeholder?: string; defaultValue: string }
|
||||
| { placeholder?: string; defaultValue?: string }
|
||||
| { placeholder: string; defaultValue?: string }
|
||||
) &
|
||||
Partial<UseFormRegisterReturn>;
|
||||
@@ -46,6 +47,7 @@ export function Select<T extends FieldValues>({
|
||||
ref,
|
||||
clearable = false,
|
||||
onClear,
|
||||
value: controlledValue,
|
||||
...props
|
||||
}: PropsType<T>) {
|
||||
const id = useId();
|
||||
@@ -54,10 +56,23 @@ export function Select<T extends FieldValues>({
|
||||
const [value, setValue] = useState(defaultValue || "");
|
||||
const error = errors && errors[name];
|
||||
|
||||
useEffect(() => {
|
||||
if (controlledValue !== undefined) {
|
||||
setValue(controlledValue);
|
||||
setIsOptionSelected(!!controlledValue);
|
||||
}
|
||||
}, [controlledValue]);
|
||||
|
||||
const handleClear = () => {
|
||||
setValue("");
|
||||
setIsOptionSelected(false);
|
||||
onClear?.();
|
||||
if (onChange) {
|
||||
const event = {
|
||||
target: { value: "" },
|
||||
} as ChangeEvent<HTMLSelectElement>;
|
||||
onChange(event);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -83,7 +98,9 @@ export function Select<T extends FieldValues>({
|
||||
ref={ref}
|
||||
value={value}
|
||||
onChange={(e) => {
|
||||
setValue(e.target.value);
|
||||
if (controlledValue === undefined) {
|
||||
setValue(e.target.value);
|
||||
}
|
||||
setIsOptionSelected(!!e.target.value);
|
||||
onChange?.(e);
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user