0

I want to unfocus all of my TextInput`s when I click on TouhableOpacity.

I have learned that I can use refs for achieve that. But when I use single ref with several TextInputs I got that behaviour with only last TextInput

class UserRegister extends React.Component<any, State> {
    private inputRef: React.RefObject<TextInput>;

    constructor(props:any) {
        super(props);
        //some code
        this.inputRef = React.createRef();
    }

    onSwitchPicker = () => {
        if (this.inputRef.current) {
            this.inputRef.current.blur();
        }

        //some code
    }

    render() {
        return (
            <KeyboardAvoidingView behavior="padding" style={styles.container}>
                <TextInput
                    ref={this.inputRef}
                    //other params
                />

                <TextInput
                    ref={this.inputRef}
                    //other params
                />

                <TouchableOpacity
                    onPress={this.onSwitchPicker}
                    //other params
                >
                //some code
                </TouchableOpacity>

                // some code
            </KeyboardAvoidingView>
        );
    }
}
Viktor
  • 1,532
  • 6
  • 22
  • 61

1 Answers1

1

If at least one input exists anyway(is not conditionally rendered), then you can set it focused and blur right next line using just single createRef().

onSwitchPicker = () => {
  this.specialInputRef.current.focus();
  this.specialInputRef.current.blur();
}

Not sure if that would scroll screen in React Native or not. If it scrolls - and this is definitely bad user experience - you can have N refs:

onSwitchPicker = () => {
  this.inputRef1.current.blur();
  this.inputRef2.current.blur();
  this.inputRef3.current.blur();
  this.inputRef4.current.blur();
}

The only way I see how to make it shorter is to have array of refs:

constructor(props) {
 super(props);
 this.inputRefs = new Array(10).fill().map(() => React.createRef());
}

onSwitchPicker = () => {
  this.inputRefs.forEach(({ current }) => {
    if (current) current.blur();
  });
}

render() {
....
 <input ref={this.inputRefs[0]} ...
...
 <input ref={this.inputRefs[1]} ...
...
 <input ref={this.inputRefs[11]} ...
....

But if there is conditional rendering I'd rather have boilerplate code instead of array. It's possible to have hard-to-catch bugs if used the same index to 2 inputs by mistake:

{someCondition && <input ref={this.inputRefs[4]} ...}
....
{someOtherCondition && <input ref={this.inputRefs[4]} ...}

Then sometimes your user will experience cases when focus stays in the field(I still don't know what's the point but guess it should affect UI in some way). But it might be hard to reproduce if user does not catch all the conditions.

skyboyer
  • 22,209
  • 7
  • 57
  • 64