react-native: Modal dismissing keyboard crash

Mac OSX react-native: 0.24.1

In the following component when clicking Cancel I get the following in the XCode console and the Modal closes then opens and then freezes.

Warning: Attempt to dismiss from view controller <UIViewController: 0x7fa152e17ca0> while a presentation or dismiss is in progress!

'use strict';
import React, {
  Component,
  View,
  Text,
  TextInput,
  TouchableOpacity,
  Dimensions,
  DeviceEventEmitter,
  LayoutAnimation,
} from 'react-native';

class Example extends Component {
  constructor(props) {
    super(props)

    var dimensions = Dimensions.get('window')

    this.state = {
      notes: '',
      width: dimensions.width,
      height: dimensions.height,
    }
  }
  componentWillMount() {
    DeviceEventEmitter.addListener('keyboardWillShow', this.keyboardWillShow)
    DeviceEventEmitter.addListener('keyboardWillHide', this.keyboardWillHide)
  }
  componentWillUnmount() {
    DeviceEventEmitter.removeAllListeners('keyboardWillShow')
    DeviceEventEmitter.removeAllListeners('keyboardWillHide')
  }
  keyboardWillShow = (e)=> {
    let height = Dimensions.get('window').height - e.endCoordinates.height - headerHeight
    LayoutAnimation.easeInEaseOut()
    this.setState({ height })
  }
  keyboardWillHide = (e)=> {
    let height = Dimensions.get('window').height - headerHeight
    LayoutAnimation.easeInEaseOut()
    this.setState({ height })
  }
  open() {
    this.setState({ open: true })
  }
  close() {
    this.setState({ open: false })
  }
  save() {
    this.setState({ open: false })
  }
  render() {
    return (
      <ScrollView keyboardShouldPersistTaps={ true }>
        <TouchableOpacity onPress={()=> this.open() }>
          <Text>Open</Text>
        </TouchableOpacity>
        <Modal
          animationType="slide"
          visible={ this.state.open }
          style={{ flex: 1 }}
        >
          <TouchableOpacity onPress={()=> this.close() }>
            <Text>Cancel</Text>
          </TouchableOpacity>
          <TouchableOpacity onPress={()=> this.save() }>
            <Text>Save</Text>
          </TouchableOpacity>
          <TextInput
            width={this.state.width}
            height={this.state.height}
            defaultValue={ this.state.notes }
            onChangeText={(notes)=> this.setState({ notes }) }
            autoFocus={ true }
            multiline={ true }
          />
        </Modal>
      </ScrollView>
    )
  }
}

When I remove keyboardShouldPersistTaps={ true } from <ScrollView> it doesn’t crash but that’s there so that clicks on these buttons works when the input has focus.

The only fix I have found so far to this issue is to dismiss the keyboard and then proceed in a timeout.

close() {
  dismissKeyboard()
  setTimeout(()=> {
    this.setState({ open: false })
  })
}

Fact: setTimeout literally fixes everything

About this issue

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

Most upvoted comments

0.40.0 has the same issue; closing a modal after a keyboard was used causes the modal to jump back up and crash the app.

Found a really great ‘work around.’ Although, probably best practice to do it this way all along.

import { Keyboard } from 'react-native'
...
Keyboard.removeAllListeners('keyboardDidHide') 
// not totally necessary and may be harmful if you do this in more than one location, works for my case
Keyboard.addListener('keyboardDidHide', () => { this.checkSubmit() })
// checkSubmit is a function the pulls up the modal
Keyboard.dismiss() 

Edit: the above chunk of code is ran through when onSubmitEditing fire’s off an a TextInput.

onSubmitEditing={ () => { this.hideKeyboard() /* <- the code above */ } } 

It’s intermittent, seems to happen much less in 0.28 but it still happens once in a while.

Here’s a screen recording: https://dl.dropboxusercontent.com/u/13632257/ModalKeyboardCrash.mov