I needed to define a component which wraps TextInput because I have a lot of text inputs in my App and I want them to have a trash-can icon to clear text and a common style.
My component is this:
import React from 'react';
import {
TextInput,
TouchableOpacity,
StyleSheet,
View,
ReturnKeyTypeOptions,
Platform,
} from 'react-native';
import Numerics from '../constants/Numerics';
import { Ionicons } from '@expo/vector-icons';
import Colors from '../constants/Colors';
interface Props {
placeholder?: string;
iconName?: string;
returnKeyType?: ReturnKeyTypeOptions;
backgroundColor?: string;
margin?: number;
marginBottom?: number;
onTextChanged?(text: string): void;
onFinishedEditing?(text: string): void;
onClearTextInput?(): void;
}
const defaultProps: Props = {
backgroundColor: Colors.textInputBackgroundColor,
placeholder: '',
iconName: '',
returnKeyType: 'none',
margin: 0,
onTextChanged: (text) => {},
onFinishedEditing: (text) => {},
marginBottom: 0,
};
const CustomTextInput: React.FC<Props> = (props) => {
const [inputText, setInputText] = React.useState('');
const onCancelSearchHandler = () => {
setInputText('');
if (props.onTextChanged) {
props.onTextChanged('');
}
if (props.onClearTextInput) props.onClearTextInput();
};
let clearTextComponent = <View></View>;
if (inputText) {
clearTextComponent = (
<TouchableOpacity onPress={onCancelSearchHandler}>
<Ionicons
name='trash-outline'
color={Colors.greyColor}
size={Numerics.iconsSize}
/>
</TouchableOpacity>
);
}
return (
<View
style={[
styles.searchBarContainer,
{
backgroundColor: props.backgroundColor,
margin: props.margin,
marginBottom: props.marginBottom,
},
]}>
<Ionicons
name={props.iconName}
color={Colors.greyColor}
size={Numerics.iconsSize}
/>
<TextInput
style={styles.textInput}
keyboardType='default'
returnKeyType={props.returnKeyType}
value={inputText}
onChangeText={(text) => {
setInputText(text);
if (props.onTextChanged) {
props.onTextChanged(text);
}
}}
onEndEditing={(event) => {
if (props.onFinishedEditing) {
props.onFinishedEditing(event.nativeEvent.text);
}
}}
placeholder={props.placeholder}
autoCorrect={false}
/>
{clearTextComponent}
</View>
);
};
CustomTextInput.defaultProps = defaultProps;
const styles = StyleSheet.create({
searchBarContainer: {
flexDirection: 'row',
backgroundColor: Colors.textInputBackgroundColor,
borderRadius: 10,
height: 50,
padding: 5,
alignItems: 'center',
},
textInput: {
flex: 1,
marginLeft: 10,
},
});
export default CustomTextInput;
The main features are:
- At the left of the TextInput there is customizable icon
- At the right of the TextInput there is a "clear text" button icon, which disappears if there's no text
- An handler that fires when text editing is ended
- The
CustomTextInputhas its own state to make the clear text button work
Everything works fine, but I really don't know how can I clear the text from the outside! Consider that I use my CustomTextInput in an App page, and when the App navigates to another page, I want to clear my CustomTextInput.
How would you do that?
CodePudding user response:
Ideal solution
inputText would be a prop, not local state and onTextChanged prop would handle change of inputText somewhere in a parent component.
Alternative solution:
useImperativeHandle hook:
const CustomTextInput = React.forwardRef((props, ref) => {
const [inputText, setInputText] = React.useState('');
const onCancelSearchHandler = () => {
setInputText('');
if (props.onTextChanged) {
props.onTextChanged('');
}
if (props.onClearTextInput) props.onClearTextInput();
};
useImperativeHandle(ref, () => ({
clear: () => {
onCancelSearchHandler();
// or just setInputText('');
}
}));
//...
})
then in parent component:
const textInputRef = useRef();
const clearInput = () => {
textInputRef.current.clear()
}
//...
<CustomTextInput ref={textInputRef} />
CodePudding user response:
If you want to clear CustomTextInput control when App navigates to another page then you can use the useEffect hook return block (similar to componentwillunmount).
useEffect(() => {
retrun () => {
onCancelSearchHandler();
}
},[]);
CodePudding user response:
You can use the useEffect hook in CustomTextInput and fire your clear procedure right before it gets unmounted (in your case when you navigate to another page).
useEffect(()=>{
// the returned function is fired right before the component is unmounted.
retrun ()=>{
// do what it takes to clear the input here
onCancelSearchHandler();
}
},[])
