I am using ReactNativePaper v4 and having a difficult time extending components with Typescript when using forwardRef
and having a compoundcomponent: TextInput.Icon
. Here is my current setup:
const InputComponent = forwardRef<
typeof RNPInput,
Omit<TextInputProps, 'theme'>
>(({ label, style, ...rest }, ref) => {
const theme = useTheme();
return (
<View>
{label && <Text>{label}</Text>}
<RNPInput
mode="outlined"
outlineColor={theme.colors.backdrop}
selectionColor={theme.colors.accent}
style={style}
// @ts-ignore
ref={ref}
theme={{ colors: { text: styles.input.color } }}
{...rest}
/>
</View>
);
});
const TextInput = Object.assign(InputComponent, {
Icon: RNPInput.Icon,
});
export { TextInput };
Then I consume like:
const Test = () => {
return <TextInput right={<TextInput.Icon name="eye"/>} />
}
The issues I have are:
- the compound component props are not found, so
name
prop is not known. - if I remove the
// @ts-ignore
, the error is:
Type '(instance: (ComponentType<Pick<TextInputProps & RefAttributes & { mode?: "flat" | "outlined" | undefined; left?: ReactNode; right?: ReactNode; ... 18 more ...; theme: Theme; } & RefAttributes<...>, "label" | ... 123 more ... | "dense"> & { ...; }> & NonReactStatics<...>) | null) => void' is not assignable to type 'string'
- If I remove the
Omit<TextInputProps, 'theme'>
form the component definition, when I consume the component, it has an error:
Property 'theme' is missing in type '{ right: Element; }' but required in type 'Omit<Props, "ref">'.
If I try to change the compound component definition to be more explicit, the Icon
is not invoked
// Explicitly type the Icon component
const Icon = (props: TextInputIconProps) => (
<RNPInput.Icon color="green" {...props} />
);
// Create the compound component
const TextInput = Object.assign(InputComponent, {
Icon,
});
How can I correctly extend the TextInput
from ReactNative paper so that: 1) forwardRef
is correctly typed, and 2) Compound component is exported so that the props are known, and 3) remove the @ts-ignore
?
I am using ReactNativePaper v4 and having a difficult time extending components with Typescript when using forwardRef
and having a compoundcomponent: TextInput.Icon
. Here is my current setup:
const InputComponent = forwardRef<
typeof RNPInput,
Omit<TextInputProps, 'theme'>
>(({ label, style, ...rest }, ref) => {
const theme = useTheme();
return (
<View>
{label && <Text>{label}</Text>}
<RNPInput
mode="outlined"
outlineColor={theme.colors.backdrop}
selectionColor={theme.colors.accent}
style={style}
// @ts-ignore
ref={ref}
theme={{ colors: { text: styles.input.color } }}
{...rest}
/>
</View>
);
});
const TextInput = Object.assign(InputComponent, {
Icon: RNPInput.Icon,
});
export { TextInput };
Then I consume like:
const Test = () => {
return <TextInput right={<TextInput.Icon name="eye"/>} />
}
The issues I have are:
- the compound component props are not found, so
name
prop is not known. - if I remove the
// @ts-ignore
, the error is:
Type '(instance: (ComponentType<Pick<TextInputProps & RefAttributes & { mode?: "flat" | "outlined" | undefined; left?: ReactNode; right?: ReactNode; ... 18 more ...; theme: Theme; } & RefAttributes<...>, "label" | ... 123 more ... | "dense"> & { ...; }> & NonReactStatics<...>) | null) => void' is not assignable to type 'string'
- If I remove the
Omit<TextInputProps, 'theme'>
form the component definition, when I consume the component, it has an error:
Property 'theme' is missing in type '{ right: Element; }' but required in type 'Omit<Props, "ref">'.
If I try to change the compound component definition to be more explicit, the Icon
is not invoked
// Explicitly type the Icon component
const Icon = (props: TextInputIconProps) => (
<RNPInput.Icon color="green" {...props} />
);
// Create the compound component
const TextInput = Object.assign(InputComponent, {
Icon,
});
How can I correctly extend the TextInput
from ReactNative paper so that: 1) forwardRef
is correctly typed, and 2) Compound component is exported so that the props are known, and 3) remove the @ts-ignore
?
1 Answer
Reset to default 0forwardRef is being deprecated https://react.dev/reference/react/forwardRef
You can just use ref instead
You can import like this
import {TextInput as TextInputReact} from 'react-native';
import {TextInput} from 'react-native-paper';
Then use your ref like this
const ref = useRef<TextInputReact | null>(null);
Then use your react-native-paper TextInput with ref as usual
<TextInput ref={ref}