lawnstarter / react-native-picker-select

🔽 A Picker component for React Native which emulates the native <select> interfaces for iOS and Android
https://npmjs.com/package/react-native-picker-select
MIT License
1.73k stars 491 forks source link

Types for PickerSelectProps['Icon'] expects React.ReactNode when runtime expects a component #488

Closed tquinlan1992 closed 7 months ago

tquinlan1992 commented 1 year ago

Describe the bug
The react-native-picker-select/index.d.ts has a type of React.ReactNode for PickerSelectProps['Icon'], but following that gives the following runtime error

Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.

Check the render method of `RNPickerSelect`.

Passing in a component has a type error, but works as expected during runtime To Reproduce
In a typescript project using the following the code will give the following typescript error. Though it works at runtime

code

import RNPickerSelect from 'react-native-picker-select';
import Icon from './Icon';

const TestComponent = () => <RNPickerSelect Icon={() => <Icon />} />

No overload matches this call. Overload 1 of 2, '(props: PickerSelectProps | Readonly): Picker', gave the following error. Type '() => JSX.Element' is not assignable to type 'ReactNode'. Overload 2 of 2, '(props: PickerSelectProps, context: any): Picker', gave the following error. Type '() => JSX.Element' is not assignable to type 'ReactNode'.


Using the following code instead will give no typescript error, but gives the error listed prior at runtime

import RNPickerSelect from 'react-native-picker-select'; import Icon from './Icon';

const TestComponent = () => <RNPickerSelect Icon={}



**Expected behavior**<br /><!-- do not remove heading -->
The expected behavior is for the types to match the runtime expectation 

**Screenshots**<br /><!-- do not remove heading -->
Add screenshots to help explain your problem. If screenshots aren't applicable to this issue, write "n/a".
"n/a"

**Additional details**<br /><!-- do not remove heading -->
-   Device: [Iphone13 Pro Max]
-   OS: [iOS15.5]
-   react-native-picker-select version: [8.0.4]
-   react-native version: [0.69.6]
-   expo sdk version: [46.0.13]

**Reproduction and/or code sample**<br /><!-- do not remove heading -->
Provide a link to a reproduction of this issue on https://snack.expo.io **or an explanation why you can not**. Not including a snack link will result in a significant delay in our ability to address this issue.

https://snack.expo.dev/iI_6XNg2f

<!-- YOU MUST FILL OUT EVERY SECTION. INCOMPLETE BUG REPORTS WILL BE CLOSED. -->
<!-- YOU MUST FILL OUT EVERY SECTION. INCOMPLETE BUG REPORTS WILL BE CLOSED. -->
Aure77 commented 1 year ago

Same issue. Seems to happen since react 18 TS types. Icon?: () => JSX.Element; should be better ?

Josh2941 commented 1 year ago

Facing the same issue.

mccraveiro commented 1 year ago

I'm using the following patch as a workaround:

diff --git a/index.d.ts b/index.d.ts
index 9f111bc0fca89c51ca7a2b666959e8ad6196bd12..09644ca8b989858021913b61625c079f96331664 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -83,7 +83,7 @@ export interface PickerSelectProps {
     pickerProps?: CustomPickerProps;
     touchableDoneProps?: CustomTouchableDoneProps;
     touchableWrapperProps?: CustomTouchableWrapperProps;
-    Icon?: React.ReactNode;
+    Icon?: React.FC;
     InputAccessoryView?: React.ReactNode;
 }
KhimGurung commented 1 year ago

@mccraveiro I am trying to patch it but it is taking forever. it keep saying installing. any idea?

mccraveiro commented 1 year ago

@KhimGurung no idea. What are you using to patch it? Yarn? patch-package? Are there any error messages?

nhotalling-viagio commented 1 year ago

@mccraveiro - thanks for providing a fix! I couldn't get patch-package to create a patch file, so I had to manually create one. Using your example, I had to add node_modules/react-native-picker-select/ to the file paths. Also had to ensure there were 2 new lines after the closing curly brace before patch-package would recognize it as a valid patch file (react-native-picker-select+8.0.4.patch)

diff --git a/node_modules/react-native-picker-select/index.d.ts b/node_modules/react-native-picker-select/index.d.ts
index 9f111bc..09644ca 100644
--- a/node_modules/react-native-picker-select/index.d.ts
+++ b/node_modules/react-native-picker-select/index.d.ts
@@ -83,7 +83,7 @@ export interface PickerSelectProps {
     pickerProps?: CustomPickerProps;
     touchableDoneProps?: CustomTouchableDoneProps;
     touchableWrapperProps?: CustomTouchableWrapperProps;
-    Icon?: React.ReactNode;
+    Icon?: React.FC;
     InputAccessoryView?: React.ReactNode;
 }
itayperry commented 10 months ago

I'm having the same issue :(

aelfannir commented 8 months ago

Workaround

<View style={{position: 'relative'}}>
    <RNPickerSelect />
    <YourIcon style={{position: 'absolute', end: 12, top: 12, zIndex: -1}}/>
</View>
lfkwtz commented 7 months ago

dupe of #478 - prs to fix this are welcome

emiliospot commented 3 months ago

this works:

// Create a custom select icon component

import React from 'react' import React from 'react'; import { StyleSheet } from 'react-native'; import { MaterialIcons } from '@expo/vector-icons';

const DropdownIcon: React.FC = () => { const styles = StyleSheet.create({ icon: { position: 'absolute', end: 0, top: 12, zIndex: -1, }, });

return ( <MaterialIcons name="keyboard-arrow-down" size={30} color="#999999" style={styles.icon} /> ); };

export default DropdownIcon;

// import and use it in Component/Screen that uses the picker: ... <RNPickerSelect //other props Icon={SelectIcon} useNativeAndroidPickerStyle={false} fixAndroidTouchableBug={true}/>