I want to make a custom component in which there is a reset button for a specific field and it appears only when there is a value in an input. The component can be controlled or not. I have made the part, but when setting the value asynchronously in react-hook-form, the reset button doesn’t appear because I don’t know how to track the change of target.value. Advise if it is possible to do this or is it better to do it differently?
const InputBase = forwardRef<HTMLInputElement, InputProps>((props, ref) => {
const innerRef = useRef<HTMLInputElement>(null!);
const [isResetVisible, setIsResetVisible] = useState(!!props.value);
useImperativeHandle(ref, () => innerRef.current, []);
useEffect(() => {
setIsResetVisible(!!props.value);
}, [props.value]);
const handleClean = useCallback(() => {
const isControlled = typeof props.value !== 'undefined';
if (!isControlled) {
innerRef.current.value = '';
setIsResetVisible(false);
}
const event = new InputEvent('change');
Object.defineProperty(event, 'target', {
value: {
...innerRef.current,
...(isControlled ? { value: '' } : {}),
},
});
props.onChange?.(event as unknown as ChangeEvent<HTMLInputElement>);
}, []);
const handleOnChange = useCallback(
(e: ChangeEvent<HTMLInputElement>) => {
if (!isResetVisible && e.target.value) {
setIsResetVisible(true);
} else if (isResetVisible && !e.target.value) {
setIsResetVisible(false);
}
props.onChange?.(e);
},
[props.onChange, isResetVisible]
);
return (
<InputGroup size="md">
<Input {...props} onChange={handleOnChange} ref={innerRef} pr="4.5rem" />
{isResetVisible && (
<InputRightElement width="4.5rem">
<Button h="1.75rem" size="sm" onClick={handleClean}>
Clear
</Button>
</InputRightElement>
)}
</InputGroup>
);
});