react-native: [0.54] [iOS] Wrong 'Backspace' event fired onKeyPress after clearing TextInput

In IOS, after clearing TextInput value (setting it to empty string) and then pressing any key (e.g. ‘a’) two onKeyPress events are fired: A, Backspace. First is for the pressed key and second is a Backspace.

Environment

Environment: OS: macOS Sierra 10.12.6 Node: 8.9.1 Yarn: 1.3.2 npm: 5.5.1 Watchman: 4.9.0 Xcode: Xcode 9.2 Build version 9C40b Android Studio: 3.0 AI-171.4443003

Packages: (wanted => installed) react: ^16.3.0-alpha.1 => 16.3.0-alpha.1 react-native: 0.54.2 => 0.54.2

Expected Behavior

Only one event for the pressed key should be fired (e. g. ‘A’).

Actual Behavior

An additional ‘Backspace’ event is fired.

Steps to Reproduce

  1. write anythig in the textfield
  2. press clear
  3. press ‘a’ >>> events ‘A’ and ‘Backspace’ will be fired
type Props = {};
type State = {
  text: string,
  keys: string
};
export default class App extends Component<Props, State> {
  state = {text: '', keys: ''}
  render() {
    return (
      <View style={styles.container}>
        <TextInput style={styles.textInput} value={this.state.text} onChangeText={this.onChangeText} onKeyPress={this.onKeyPress}/>
        <Button title="Clear" onPress={this.onClear}/>
        <Text>Text: {this.state.text}</Text>
        <Text>Keys: {this.state.keys}</Text>
      </View>
    );
  }

  onChangeText = (text: string) => {
    this.setState({text})
  }

  onKeyPress = ({ nativeEvent }: Object) => {
    this.setState({keys: this.state.keys + nativeEvent.key + ', '})
  }

  onClear = () => {
    this.setState({text: '', keys: ''})
  }
}

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 15
  • Comments: 19 (5 by maintainers)

Commits related to this issue

Most upvoted comments

I was able to workaround this bug by adding a check in the onKeyPress callback function,

 onKeyPress(e) {
    if (e.nativeEvent.key === 'Backspace') {
      // Return if duration between previous key press and backspace is less than 20ms
      if (Math.abs(this.lastKeyEventTimestamp - e.timeStamp) < 20) return;

      // Your code here
 
    } else {
      // Record non-backspace key event time stamp
      this.lastKeyEventTimestamp = e.timeStamp;
    }
  }

I found while debugging that duration between receiving backspace event after key press is less than ~10ms. So I record the non-backspace key event timeStamp and use it to compare with backspace event timeStamp. If the difference between these two is less than 20ms (arbitrary value > 10ms) then I return from the callback. Hope this helps!

I opened a pull request to fix this bug: #18627

+1; I’ve got the same issue on 0.54.

Fix should be in react-native@0.56.0-rc.2!

Fixed.

Thanks for posting this! It looks like your issue may refer to an older version of React Native. Can you reproduce the issue on the latest release, v0.55?

Thank you for your contributions.