Skip to content

Commit b0b7c46

Browse files
author
Mohsen Ghaemaghami
committed
refactor: use React 19 of passing ref
- Changed imports from React to type imports for better type safety. - Refactored TextField to use a standard function instead of React.forwardRef, enhancing clarity. - Updated TextInput to support ref prop directly, ensuring consistent ref handling across components.
1 parent 45b628c commit b0b7c46

3 files changed

Lines changed: 65 additions & 53 deletions

File tree

packages/components/src/remix-hook-form/text-field.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import * as React from 'react';
1+
import type * as React from 'react';
22
import { TextField as BaseTextField, type TextInputProps as BaseTextFieldProps } from '../ui/text-field';
33
import { FormControl, FormDescription, FormLabel, FormMessage } from './form';
44

55
import { useRemixFormContext } from 'remix-hook-form';
66

77
export type TextFieldProps = Omit<BaseTextFieldProps, 'control'>;
88

9-
export const TextField = React.forwardRef<HTMLInputElement, TextFieldProps>((props, ref) => {
9+
export const TextField = function RemixTextField(props: TextFieldProps & { ref?: React.Ref<HTMLInputElement> }) {
1010
const { control } = useRemixFormContext();
1111

1212
// Merge the provided components with the default form components
@@ -22,7 +22,7 @@ export const TextField = React.forwardRef<HTMLInputElement, TextFieldProps>((pro
2222
...props.components,
2323
};
2424

25-
return <BaseTextField ref={ref} control={control} components={components} {...props} />;
26-
});
25+
return <BaseTextField control={control} components={components} {...props} />;
26+
};
2727

2828
TextField.displayName = 'RemixTextField';

packages/components/src/ui/text-field.tsx

Lines changed: 54 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import * as React from 'react';
1+
import type * as React from 'react';
22
import type { Control, FieldPath, FieldValues } from 'react-hook-form';
33
import {
44
type FieldComponents,
@@ -64,50 +64,59 @@ export interface TextInputProps extends Omit<InputProps, 'prefix' | 'suffix'> {
6464
className?: string;
6565
}
6666

67-
export const TextField = React.forwardRef<HTMLInputElement, TextInputProps>(
68-
({ control, name, label, description, className, components, prefix, suffix, ...props }, ref) => {
69-
// Use the custom Input component if provided, otherwise use the default TextInput
70-
const InputComponent = components?.Input || TextInput;
67+
export const TextField = function TextField({
68+
control,
69+
name,
70+
label,
71+
description,
72+
className,
73+
components,
74+
prefix,
75+
suffix,
76+
ref,
77+
...props
78+
}: TextInputProps & { ref?: React.Ref<HTMLInputElement> }) {
79+
// Use the custom Input component if provided, otherwise use the default TextInput
80+
const InputComponent = components?.Input || TextInput;
7181

72-
return (
73-
<FormField
74-
control={control}
75-
name={name}
76-
render={({ field, fieldState }) => {
77-
return (
78-
<FormItem className={className}>
79-
{label && <FormLabel Component={components?.FormLabel}>{label}</FormLabel>}
80-
<div
81-
className={cn('flex group transition-all duration-200 rounded-md', {
82-
'field__input--with-prefix': prefix,
83-
'field__input--with-suffix': suffix,
84-
'focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2 focus-within:ring-offset-background': true,
85-
})}
86-
>
87-
{prefix && <FieldPrefix>{prefix}</FieldPrefix>}
88-
<FormControl Component={components?.FormControl}>
89-
<InputComponent
90-
{...field}
91-
{...props}
92-
ref={ref}
93-
className={cn('focus-visible:ring-0 focus-visible:ring-offset-0 border-input', {
94-
'rounded-l-none border-l-0': prefix,
95-
'rounded-r-none border-r-0': suffix,
96-
})}
97-
/>
98-
</FormControl>
99-
{suffix && <FieldSuffix>{suffix}</FieldSuffix>}
100-
</div>
101-
{description && <FormDescription Component={components?.FormDescription}>{description}</FormDescription>}
102-
{fieldState.error && (
103-
<FormMessage Component={components?.FormMessage}>{fieldState.error.message}</FormMessage>
104-
)}
105-
</FormItem>
106-
);
107-
}}
108-
/>
109-
);
110-
},
111-
);
82+
return (
83+
<FormField
84+
control={control}
85+
name={name}
86+
render={({ field, fieldState }) => {
87+
return (
88+
<FormItem className={className}>
89+
{label && <FormLabel Component={components?.FormLabel}>{label}</FormLabel>}
90+
<div
91+
className={cn('flex group transition-all duration-200 rounded-md', {
92+
'field__input--with-prefix': prefix,
93+
'field__input--with-suffix': suffix,
94+
'focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2 focus-within:ring-offset-background': true,
95+
})}
96+
>
97+
{prefix && <FieldPrefix>{prefix}</FieldPrefix>}
98+
<FormControl Component={components?.FormControl}>
99+
<InputComponent
100+
{...field}
101+
{...props}
102+
ref={ref}
103+
className={cn('focus-visible:ring-0 focus-visible:ring-offset-0 border-input', {
104+
'rounded-l-none border-l-0': prefix,
105+
'rounded-r-none border-r-0': suffix,
106+
})}
107+
/>
108+
</FormControl>
109+
{suffix && <FieldSuffix>{suffix}</FieldSuffix>}
110+
</div>
111+
{description && <FormDescription Component={components?.FormDescription}>{description}</FormDescription>}
112+
{fieldState.error && (
113+
<FormMessage Component={components?.FormMessage}>{fieldState.error.message}</FormMessage>
114+
)}
115+
</FormItem>
116+
);
117+
}}
118+
/>
119+
);
120+
};
112121

113122
TextField.displayName = 'TextField';

packages/components/src/ui/text-input.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
import * as React from 'react';
1+
import type * as React from 'react';
22
import { cn } from './utils';
33

4-
export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {}
4+
export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
5+
ref?: React.Ref<HTMLInputElement>;
6+
}
57

6-
const TextInput = React.forwardRef<HTMLInputElement, InputProps>(({ className, type, ...props }, ref) => {
8+
function TextInput({ className, type, ref, ...props }: InputProps) {
79
return (
810
<input
911
ref={ref}
@@ -16,7 +18,8 @@ const TextInput = React.forwardRef<HTMLInputElement, InputProps>(({ className, t
1618
{...props}
1719
/>
1820
);
19-
});
21+
}
22+
2023
TextInput.displayName = 'TextInput';
2124

2225
export { TextInput };

0 commit comments

Comments
 (0)