Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native "interactive" keyboardDismissMode throws error when dragged

The error is: RCTLayoutAnimationGroup expects timings to be in ms, not seconds

This occurs as I drag the keyboard downwards quickly. Sometimes it happens; sometimes it doesn't.

I am using a simple TextInput component, within a KeyboardAvoidingView

like image 454
TIMEX Avatar asked Oct 08 '18 09:10

TIMEX


People also ask

Is scrollTo deprecated?

scrollTo()This is deprecated due to ambiguity (y before x), and SHOULD NOT BE USED.

How do I fix my keyboard in react native?

This issue can be solved by using the keyboardDismissMode='on-drag' property on Scrollview and Content, which will make the keyboard to get disappear automatically on scrolling. Read our article on Why is React Native the best for Mobile App Development?


1 Answers

Adding bounces={false} to your ScrollView seems to solve the issue.

<ScrollView keyboardDismissMode="interactive" bounces={false}>

It changes the behaviour a bit as well but, the error doesn't seem to appear anymore.

I think if you wish to keep the 'bouncy' behaviour of the ScrollView, the best way would be to make the 'bounces' dependent on the keyboard show. When the keyboard is shown, the bounces is set to false. Have a look at my sample component:

export default class App extends Component<Props> {

constructor(){
  super();
  this.state = {
    bounces: true
  }
  this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this._keyboardDidHide.bind(this));
  this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._keyboardDidShow.bind(this));
}

_keyboardDidShow(){
  this.setState({bounces: false});
}

_keyboardDidHide(){
  this.setState({bounces: true});
}

  render() {
    return (
      <KeyboardAvoidingView style={styles.container}  behavior="padding" enabled>
      <ScrollView keyboardDismissMode="interactive" bounces={this.state.bounces}>
      <TextInput
        style={{height: 40, width: 150, borderColor: 'gray', borderWidth: 1}}
      />
      </ScrollView>

      </KeyboardAvoidingView>
    );
  }
}

EDIT:

A RNT hack would be to override the duration when it is less than 10(ms). For you it should be to change: node_modules/react-native/Libraries/Components/Keyboard/KeyboardAvoidingView.js method: scheduleLayoutAnimation change:

const {duration, easing, endCoordinates} = event;

to:

let {duration, easing, endCoordinates} = event;

and add:

if(duration < 10){
    duration = 10;
}

inside the if (duration && easing) condition.

This will make sure the shortest duration is 1ms and never less, thus the duration is not going to be thrown anymore.

My KeyboardAvoidingView.js, _onKeyboardChange method looks something like this:

_onKeyboardChange = (event: ?KeyboardEvent) => {
    if (event == null) {
      this.setState({bottom: 0});
      return;
    }

    let {duration, easing, endCoordinates} = event;
    const height = this._relativeKeyboardHeight(endCoordinates);

    if (this.state.bottom === height) {
      return;
    }

    if (duration && easing) {
      if(duration < 10){
        duration = 10;
    }
      LayoutAnimation.configureNext({
        duration: duration,
        update: {
          duration: duration,
          type: LayoutAnimation.Types[easing] || 'keyboard',
        },
      });
    }
    this.setState({bottom: height});
  };

EDIT 2:

I submitted an issue to RNT team, and opened a PR to them: https://github.com/facebook/react-native/pull/21858

EDIT 3: The fix was merged to react native master: https://github.com/facebook/react-native/commit/87b65339379362f9db77ae3f5c9fa8934da34b25

like image 123
Lukasz Avatar answered Sep 21 '22 08:09

Lukasz