I have a screen where I use this :
const [searchText, setSearchText] = useState('');
<Item rounded style={styles.inputItem}>
<Icon
name="search"
size={moderateScale(18)}
color="#bdbdbd"
style={styles.icon}
/>
<Input
autoFocus={true}
autoCapitalize="none"
style={styles.inputField}
placeholder="Friend Search"
keyboardType="default"
onChangeText={(text: string) => {
setSearchText(text);
}}
/>
</Item>
Instead of using the Input element on my current screen, I want to turn it into a reusable component. Something like this:
type SearchInputProps = {
handleChange?: any;
};
export const SearchInput: React.FunctionComponent<SearchInputProps> = (handleChange) => {
return (
<Item rounded style={styles.inputItem}>
<Icon name='search' size={moderateScale(18)} color="#bdbdbd" style={styles.icon}/>
<Input
autoFocus={true}
autoCapitalize="none"
style={styles.inputField}
placeholder="Friend Search"
onChangeText={()=>handleChange}
/>
</Item>
);
};
However, I am unable to figure out how to make the onChangeText
work such that the const [searchText, setSearchText] = useState('');
value from the main screen can be set over there. Is it even possible?
I tried to create a snack expo here but I am unable to install native base https://snack.expo.io/@nhammad/curious-bubblegum
Edit:
Managed to resolve the type error but still don't know how to pass setSearchText
while calling the component.
type SearchInputProps = React.PropsWithRef<{
handleChange?: any;
}>;
export const FieldInput = React.forwardRef<Input, SearchInputProps>(
({ handleChange }) => {
return (
<Item rounded style={styles.inputItem}>
<Icon
name="search"
size={moderateScale(18)}
color="#bdbdbd"
style={styles.icon}
/>
<Input
autoFocus={true}
autoCapitalize="none"
style={styles.inputField}
placeholder="Friend Search"
keyboardType="default"
onChangeText={handleChange}
/>
</Item>
);
},
);
You can create a reusable Input
component by containing common behavior inside the component and then exposing the APIs to consumer component through props. Here is a Snack example. Please check the Input
component inside components folder.
import React, {useState} from 'react';
import { StyleSheet, Text, TextInput as RnTextInput, View } from 'react-native';
const Input = ({label, onFocus, ...rest}) => {
const [isFocussed, setIsFocussed] = useState(false);
const handleFocus = () => {
setIsFocussed(true);
onFocus && onFocus();
};
return (
<View style={[styles.container, isFocussed && styles.inputFocused]}>
<Text style={styles.label}>{label}</Text>
<RnTextInput
style={styles.input}
onFocus={handleFocus}
{...rest}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
margin: 5,
borderBottomWidth: 1,
borderBottomColor: '#d3d3d3',
},
label: {
color: 'red',
},
input: {
height: 40,
fontSize: 16,
paddingLeft: 10,
},
inputFocused: {
borderBottomColor: 'blue'
}
})
export default Input;
Then use the component like this:
<Input
label="Enter Name"
onChangeText={text => onChangeText(text)}
onFocus={handleOnFocus}
placeholder="Enter some value"
value={value}
/>
Note: I have used React Native inbuilt TextInput
but as per my initial impression native-base
's Input
has same API as RN TextInput
.