This is my code in which I tried navigation in alert and if I write Alert.alert in my code, alert won't be shown. Why?
if (results.rowsAffected > 0) {
alert('Card Add Successfully ',
[
{
text: 'OK',
onPress: () => navigation.navigate('Home')
},
],
{ cancelable: false }
);
} else alert('Failed!');
use like this:
import { Alert } from 'react-native';
...
Alert.alert('Title','Card Add Successfully ',
[
{
text: 'OK',
onPress: () => navigation.navigate('Home')
},
],
{ cancelable: false }
);
because alert is a window method and doesn't implement the prop onPress, so you need to import react native Alert in order to pass your desired function to onPress.
Related
I am a beginner. I am trying to pass three parameters. The third one will be an object that will contain the actions and their text value. How can I do that?
import { Alert } from 'react-native';
export const Calert = (title,message,[{}]) => {
let Ctitle = title;
let Cmessage = message;
Alert.alert(
Ctitle,
Cmessage,
[
action
]
)
}
You can use Alert in this way like
const action = [
{text: 'OK', onPress: () => alert('OK')},
{text: 'Cancel', onPress: () => alert('Cancel')},
]
Alert.alert('Title', 'Message', action);
I am trying to make an alert when the user clicks back button where he will be offered with two options, Yes or No. If the user clicks "No" the user will stay on that screen and if the user presses "Yes" then, I want some different screen to be shown.
Basically I want to prevent user from going back to the previous screen and instead redirect the user to some another screen.
Here is the example useEffect code that I am trying to make this work:
useEffect(() => {
navigation.addListener('beforeRemove', (e) => {
e.preventDefault();
Alert.alert(
'Registration Process',
'Are you sure you want to cancel the registration process?',
[
{
text: 'Yes',
style: 'destructive',
// If the user confirmed, then we dispatch the action we blocked earlier
// This will continue the action that had triggered the removal of the screen
onPress: () => {
// navigation.dispatch(e.data.action);
navigation.navigate('SignUp'); // On pressing Yes, user should be shown this screen.
},
},
{text: 'No', style: 'cancel', onPress: () => {}},
],
);
});
}, [navigation]);
After running the app, when I press "Yes" I get treated with the alert box again and again.
You can create a hook and call it on backpress on when user tries to leave the page
Create a folder called hooks where your App.js is located.
Inside that create a file called useBackHandler.ts
Inside useBackHandler.ts paste this
import { useEffect } from 'react';
import { BackHandler } from 'react-native';
export function useBackHandler(handler: () => boolean) {
useEffect(() => {
BackHandler.addEventListener('hardwareBackPress', handler);
return () => BackHandler.removeEventListener('hardwareBackPress', handler);
}, [handler]);
}
Then in your RegisterScreen create a function to execute on backpress or when user wants to goBack like this
const AlertConfirmation = () => {
Alert.alert(
'Registration Process',
'Are you sure you want to cancel the registration process?',
[
{
text: 'Yes',
style: 'destructive',
onPress: () => {
navigation.navigate('ScreenOne');
},
},
{ text: 'No', style: 'cancel', onPress: () => {} },
]
);
};
I've created a Snack for you to see working example..
Check this out.
I'm trying to set alert function before running delete function to confirm.
Here is my code.
Now this shows alert popup with title, explanation and two buttons as I expected.
However, after showing up alert, the machine stopped for about one minute.
I can not press anything.
After that, I can press both buttons, but nothing happens - neither console.log nor delete function.
How can I fix this? thanks
import React from 'react';
import { StyleSheet, View, Text, TouchableOpacity, Alert } from 'react-native';
import CircleButton from '../elements/CircleButton';
handlePress() {
const { currentUser } = firebase.auth();
const db = firebase.firestore();
db.collection(`users/${currentUser.uid}/friends`).doc(this.state.key).delete()
.then(() => {
console.log('Deleted');
this.props.navigation.goBack();
})
.catch((error) => {
console.log(error);
});
}
...
<CircleButton
style={styles.funcButton}
onPress={()=>{
Alert.alert(
'Are you sure to delete?',
'never recover',
[
{text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'},
{text: 'Delete', onPress: () => this.handlePress.bind(this), style: 'destructive'},
],
{ cancelable: false }
)
}}>
{'\uf1f8'}
</CircleButton>
Change
{text: 'Delete', onPress: () => this.handlePress.bind(this), style: 'destructive'},
to
{text: 'Delete', onPress: this.handlePress, style: 'destructive'},
Because
arrow functions don’t bind this.
I am trying to show an alert when using a switch (atm only on Ios), but it shows an error:
JSON value '({text = OK;})' of type NSMutableArray cannot be converted to NSString
This is an example of the code I am using:
import React, { Component } from 'react';
import { StyleSheet,Text,View,Button,TouchableOpacity,TextInput,AsyncStorage,ScrollView, Alert,Switch } from 'react-native';
import RNRestart from 'react-native-restart';
export default class ProfileScreen extends Component {
constructor(props) {
super(props);
this.state = {
colorPattern: false
}
}
saveThemeColour(color) {
if(color) {
AsyncStorage.setItem('themeColour', 'default');
this.setState({colorPattern: true});
Alert.alert(
I18n.t('restart theme change'),
[
{text: 'OK', onPress: () => RNRestart.Restart()}
],
{ cancelable: false }
)
}else{
AsyncStorage.setItem('themeColour', 'white');
this.setState({colorPattern: false});
}
}
<Switch value={this.state.colorPattern} onValueChange={ (value) => this.saveThemeColour(value)}/>
}
It works fine when I just leave the title of the alert.
You are missing the message parameter:
Alert.alert(
I18n.t('restart theme change'),
<here-comes-the-message-as-string>,
[
{text: 'OK', onPress: () => RNRestart.Restart()}
],
{ cancelable: false }
)
From my observation, the Alert dialog seems built on top of the React Native app.
So it pops out everytime you call it, and doesn't to be in the render function.
The catch is it is not an async task so the code after Alert will continue to execute regardless the callback function.
The code below demonstrates a situation where the Alert dialog keeps popping out because it reads the same barcode over and over again.
(It is written in TypeScript. Just take my word, this is a valid snippet.)
import * as React from "react";
import Camera from "react-native-camera";
import { Alert } from "react-native";
export default class BarcodeScanSreen extends React.Component<any ,any> {
private _camera;
private _onBarCodeRead = e => {
if (e.type === "QR_CODE") {
Alert.alert(
"QRCode detected",
"Do you like to run the QRCode?",
[
{ text: "No", onPress: this._onNoPress },
{ text: "Yes", onPress: this._onYesPress }
],
{ cancelable: false }
);
}
};
private _onYesPress = () => { /* process the QRCode */ }
private _onNoPress = () => { /* close the alert dialog. */ }
render() {
return (
<Camera
onBarCodeRead={this._onBarCodeRead}
aspect={Camera.constants.Aspect.fill}
ref={ref => (this._camera = ref)}
>
{/* Some another somponents which on top of the camera preview... */}
</Camera>
);
}
}
Is there a way to pause the JS code and await the response from Alert?
React-native Alert doesn't stop the execution of code below it. By changing it to async function which resolves the promise on user action will work as ASYNC-Alert.
const AsyncAlert = async () => new Promise((resolve) => {
Alert.alert(
'info',
'Message',
[
{
text: 'ok',
onPress: () => {
resolve('YES');
},
},
],
{ cancelable: false },
);
});
await AsyncAlert();
Use react-native-alert-async
I've just published a package that does exactly this and permit to await for the choice of the user. It is compatible with Expo.
import AlertAsync from "react-native-alert-async";
const myAction = async () => {
const choice = await AlertAsync(
'Title',
'Message',
[
{text: 'Yes', onPress: () => 'yes'},
{text: 'No', onPress: () => Promise.resolve('no')},
],
{
cancelable: true,
onDismiss: () => 'no',
},
);
if (choice === 'yes') {
doSomething();
}
else {
doSomethingElse();
}
}
Original answer: I've made a PR to ReactNative for this feature: https://github.com/facebook/react-native/pull/20312
Here's a simple solution.
The trick used here is to make a function that calls the button's onPress function, then resolve the promise with the index of the button. Note that this requires the alert to be uncancellable.
showAsyncAlert = (title, message, buttons, options) => {
return new Promise((resolve, reject) => {
// We can't detect a cancellation, so make sure the Alert is not cancellable.
options.cancellable = false
buttons.forEach((button, index) => {
let onPress = button.onPress
button.onPress = option => {
if (onPress) {
onPress(option)
}
resolve(index)
}
})
Alert.alert(title, message, buttons, options)
})
}
Usage:
let option = await showAsyncAlert(title, message, buttons options)
if (option === 0) {
foo()
} else {
bar()
}
Alert does not pause the code. In this case JS is not the only problem - the Camera component also keeps running in the background which is native and it will trigger the onBarCodeRead listener, regardless if the Alert is present or not.
You could try to stop the camera at the beginning on _onBarCodeRead with the stopPreview() method mentioned in the docs.
Also note that react-native-camera is currently in a migration process from Camera (RCTCamera) to RNCamera and in the new RNCamera I don't see a stopPreview() method. Anyhow, a simple flag would also do the job.
I have some workaround for this,If you have alert function like below
Alert.alert(
'Delete comment?',
'Are you sure you want to delete this comment?',
[
{
text: 'Cancel',
onPress: () => console.log('Cancel Pressed'),
style: 'cancel',
},
{ text: 'yes', onPress:() => this.props.deleteComment(commentId),
],
{ cancelable: false },
);
//call after comment is deleted
refreshPage();
This code does not wait for alert's response, it will execute refreshPage() immediately.
so, you can do something like
Alert.alert(
'Delete comment?',
'Are you sure you want to delete this comment?',
[
{
text: 'Cancel',
onPress: () => console.log('Cancel Pressed'),
style: 'cancel',
},
{ text: 'yes', onPress: async () => {await this.props.deleteComment(commentId);refreshPage();},
],
{ cancelable: false },
);
If you need to return a promise:
const asyncAlert = (title, message, callback) => (new Promise((resolve) => {
Alert.alert(
title,
message,
[{ text: "Cancel" }, { text: "OK", onPress: () => resolve() }], { cancelable: false }
);
}).then(callback));
Usage:
return asyncAlert("My Title", "Are you sure?", () => SOME_PROMISE_FUNCTION())