Closed BrendanC23 closed 5 months ago
This is an interesting issue.
Both react-hook-form and mantine require ref, so it's being overwritten by the react-hook-form-ref.
One potential solution from my side would be switch the order of
{...field}
{...props}
and allow ref to come from the parent component. I'll need to think about this.
Found something related to this:
https://www.react-hook-form.com/faqs/#Howtosharerefusage
I'll need to figure how to share that ref usage
Here's where I'm at
Change components to use forwardRef. Taking your example of NumberInput
import { forwardRef } from "react";
import {
type UseControllerProps,
useController,
type FieldValues,
} from "react-hook-form";
import {
NumberInput as $NumberInput,
type NumberInputProps as $NumberInputProps,
} from "@mantine/core";
export type NumberInputProps<T extends FieldValues> = UseControllerProps<T> &
Omit<$NumberInputProps, "value" | "defaultValue">;
export const NumberInput = forwardRef(function NumberInput<
T extends FieldValues,
>(
{
name,
control,
defaultValue,
rules,
shouldUnregister,
onChange,
...props
}: NumberInputProps<T>,
ref: React.Ref<HTMLInputElement>,
) {
const {
field: { value, onChange: fieldOnChange, ref: insideRef, ...field },
fieldState,
} = useController<T>({
name,
control,
defaultValue,
rules,
shouldUnregister,
});
return (
<$NumberInput
ref={mergedRef}
value={value}
onChange={(e) => {
fieldOnChange(e);
onChange?.(e);
}}
error={fieldState.error?.message}
{...field}
{...props}
/>
);
});
This now breaks generics. In App.tsx,
<NumberInput
name="numberInput"
// ts error here due to not forwarding generics
control={control}
placeholder="Your age"
label="Your age"
withAsterisk
/>
I looked into solutions such https://fettblog.eu/typescript-react-generic-forward-refs/, https://stackoverflow.com/questions/58469229/react-with-typescript-generics-while-using-react-forwardref. I settled on redeclaring forwardRef.
// Redecalare forwardRef
declare module "react" {
function forwardRef<T, P = {}>(
render: (props: P, ref: React.Ref<T>) => React.ReactNode | null,
): (props: P & React.RefAttributes<T>) => React.ReactNode | null;
}
The you need to find a way to merge refs using https://chakra-ui.com/docs/hooks/use-merge-refs or https://github.com/gregberge/react-merge-refs/tree/main/src
const mergedRef = useMergeRefs(insideRef, ref);
return (
<$NumberInput
ref={mergedRef}
value={value}
onChange={(e) => {
fieldOnChange(e);
onChange?.(e);
}}
error={fieldState.error?.message}
{...field}
{...props}
/>
now that you've re-declared react forward ref, all the react things aren't working well.
If you find a good way to solve these 2 issues, PR is welcome.
Here's a sample branch if you want this feature to be supported: https://github.com/aranlucas/react-hook-form-mantine/tree/forwardRef
Hopefully you find a better way to do make it compatible.
Stale issue message
can we reopen this?
Stale issue message
What is the suggested way to use the react-hook-form-mantine components with Mantine's Tooltip? If I do
I get the error
Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
Mantine's Tooltip documentation says to use a
ref
prop (and that the default Mantine components have this built-in already).I tried doing
but got the error
Property 'ref' does not exist on type 'IntrinsicAttributes & UseControllerProps<...>
.Here's a StackBlitz of the issue. There is a console error for attempt 1 and a TypeScript error for attempt 2.