Home > Enterprise >  React Native TextInput wrapper component, how to clear the value from "outside"
React Native TextInput wrapper component, how to clear the value from "outside"

Time:01-10

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 CustomTextInput has 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();
  }

},[])
  •  Tags:  
  • Related