How to close react-native modal on pressing escape key? (iOS) - ios

Is it possible to close react-native 'Modal' on pressing the escape key? I know other libraries 'react-modal' where Modal closes on pressing escape key out of box. But seems react-native Modal doesn't have this functionality out of box.
import { Modal } from "react-native";
<Modal
visible={isOpen}
transparent={true}
animationType={"fade"}
onRequestClose={() => {
console.log("On request close");
this.closeModal();
}}
>
<View>
// Other UI elements here
</View>
</Modal>
"onRequestClose" is not called when Escape key is pressed. Any workaround on how to close modal on pressing escape key?
Note: There is no TextInput which I have seen being suggested in few answers to capture key press events, so that cannot be used.

Related

React Native/Expo: Modal not showing when 'visible' prop is true on iOS

I have an app that I've built in React Native where I have a modal that will appear when a button is pressed and prompts the user for input. I've made other modals in the app that work fine using the same method that I am using now. But when I change the state for this modal that determines whether the modal is visible, it seems to completely ignore it and does not display. The modal works on my android and on my many android emulators but it does not work on my iphone 10 for some reason.
I have a file GameScreen.js that is the screen component and holds the modal within it. It also holds the relevant methods and state for the modal's visibility:
import {
Body,
Button,
Container,
Content,
Header,
Icon,
Left,
Right,
View } from 'native-base';
import { BackHandler, StyleSheet, Text, TextInput, TouchableOpacity, Platform } from 'react-native';
import React, { Component, createRef } from 'react';
import myModal from '../components/myModal';
export default class GameScreen extends Component {
constructor(props) {
super(props)
this.state = {
// other state
isVisible: false,
}
this.displayModal = this.displayModal.bind(this);
}
displayModal(show) {
this.setState({
isVisible: show
})
}
render() {
return (
<Container>
<myModal
displayModal={this.displayModal}
isVisible={this.state.isVisible}
/>
<View>
<TouchableOpacity
style={styles.button}
onPress{() => this.displayModal(true)} >
<Image />
</TouchableOpacity>
</View>
</Container>
)
}
}
I have the modal in its own file and it looks like this (myModal.js):
import {
Button,
Card,
CardItem,
Container,
Text,
View } from 'native-base';
import { Modal, StyleSheet } from 'react-native';
import React, { Component } from 'react';
export default class myModal extends Component {
render() {
return (
<Container>
<Modal
transparent
animationType='fade'
visible={this.props.isVisible}
onRequestClose={() => this.props.displayModal(false)}
>
<View>
// My view stuff
</View>
</Modal>
</Container>
)
}
}
I have tried putting console logs in the modal file to see if the state is actually changing and it does seem to be. I've added a log of the isVisible state in render() and in a componentDidUpdate() and it always logs out true once I have pressed the button in GameScreen but it seems like the modal is ignoring it. When I manually change the 'visible' prop to true it displays fine so it's not as if it has a problem with what I want to render.
I've also tried to run expo in production mode as some people have cited issues with dev mode and react native modals. I started the metro bundler with 'expo start --no-dev --minify' as the expo docs suggest but the problem persists.
As I said above, this exact approach is working fine in other parts of the app but seems to not like the GameScreen for some reason. And, this problem ONLY happens on iOS. I don't have any other iphones and don't have an access to a mac for xCode so I guess it might be the phone itself but it renders the other modals I have on my app just fine. I've been banging my head on the keyboard trying to get this weird bug figured out for a while, so thank you for any responses!!
So I just now figured it out and it was a dumb solution that I hope will help someone else. Thank you #Kamal Hossain, your suggestion helped me diagnose the problem.
So in my GameScreen, I was using an API called react-native-actions-sheet which is this nice little drawer UI component which held the button that was trying to open the modal. The button also closed the drawer after it was pressed. The button was interacting with the state just fine, but I think the process of closing the drawer was messing with the modal rendering somehow.
My working solution is to make the button wait for a fraction of a second before attempting to open the modal on ios and it works just fine now:
<TouchableOpacity
onPress={() => {
// closes drawer
this.props.toggleActionSheetVisibility();
// waits if on ios and then opens modal
setTimeout(() => this.displayModal(true), Platform.OS === "ios" ? 200 : 0);
}}
/>
I don't know why it was only happening on ios specifically but I hope this helps someone in the future.

React Native (IOS) - Not able to press on components after closing a modal

Description
I'm not able to press on other components after closing a modal
React Native version:
0.63.0
Steps To Reproduce
After loading the screen, try to interact with the components
Open the popup by clicking in the bottom button
Try to interact with the components again
The video reproducing the issue: https://streamable.com/1bb89k
Expected Results
The components should stay interactable after closing the modal
Link to the repository:
https://github.com/LauraBeatris/bill-splitting
Modal
https://github.com/LauraBeatris/bill-splitting/blob/master/src/contexts/popup/PopupContainer.ts
<PopupProvider value={payload}>
<Popup
isOpen={popupState.isOpen}
hidePopup={hidePopup}
handleOnShow={handleOnShow}
handleOnHide={handleOnHide}
>
{
Component && (
<Component
hidePopup={hidePopup}
showPopup={showPopup}
{...componentProps}
/>
)
}
</Popup>
{children}
</PopupProvider>

IOS Keyboard disappear randomly on web input

I experience a weird ios keyboard issue on our pwa web page.
As the photo below, the keyboard body disppear while the toolbar remains. And once this situation appear, it will keep like that until I restart the pwa app.
We use react and the input element is a Material-ui Textfield. While there have some conditional render on parent component
function handleChange(e) {
var value = e.target.value;
setValue(value);
return 0
};
<MaterialUi_TextField
inputProps={"title": "quantity", "onFocus": onFocus, "onBlur": onBlur}
type={"number"}
value={value}
onChange={handleChange}
/>;
other info to mention:
ios version = 13.4.1, 13.6
there is a meta user-scalable=0 on the page

onSubmitEditing not triggered on numeric iOS keyboard

In my React Native application, I have two TextInput components, one numeric and one default. The problem is that, onSubmitEditing works on the default keyboard on both iOS and Android, but it's not triggered on the numeric keyboard on iOS.
Default keyboard:
I use the default keyboardType in the example below. onSubmitEditing is triggered both on Android and iOS.
<TextInput
value={this.state.username}
onChangeText={(username) => this.setState({ username })}
onSubmitEditing={() => console.log('onSubmitEditing triggered')}
/>
Android keyboard has a tick-button and iOS keyboard has a return button. When I press these buttons, onSubmitEditing is triggered on both keyboards.
Numeric keyboard:
I used the numeric keyboardType in the following example. I added returnKeyType="done", because iOS keyboard does now show a button without setting returnKeyType.
<TextInput
value={this.state.password}
keyboardType="numeric"
onChangeText={(password) => this.setState({ password })}
onSubmitEditing={() => console.log('onSubmitEditing triggered')}
returnKeyType="done"
/>
Android keyboard shows a tick-button and it triggers onSubmitEditing when pressed. iOS keyboard shows a Done button above the keyboard, however it does not trigger onSubmitEditing.
I have tried using onEndEditing prop, but it does not work as onSubmitEditing. It is triggered on blur events too. onSubmitEditing is only triggered when the return key button is pressed, and that's what I exactly need.

IBM Worklight 6.1 - How to detect the keyboard's "Search" button?

We are developing a hybrid mobile app using IBM Worklight 6.1.
For iOS, how to handle "Search" button event from the soft keypad that is displayed?
"handle" is a bit vague... What are you trying to accomplish?
You shouldn't need to detect any button, if you invoke the correct keyboard for the specific need.
The search button in the iOS keyboard will only appear if your input tag is inside a form element.
For example:
// This will display a return button.
<input id="textField" type="text"/>
// This will display a search button.
<form>
<input id="searchField" type="search"/>
</form>
In JavaScript, you can use the jQuery keypress event to trigger an action once the search button is tapped. For example:
$("#searchField").keypress(function() {
alert("Handler for .keypress() called.");
});
You could also "detect" the "type" of the keyboard, in the case of "search", like the following (but this is kinda obvious...):
if ($("#searchField").attr("type") == "search") {
alert("This search field is of type 'search'.");
}
Otherwise, you will need to implement native code (meaning a Cordova plug-in) to detect the type of the currently displayed keyboard and perform actions, etc...

Resources