React native 如何在React Native中等待警报对话框的响应?
据我观察,React native 如何在React Native中等待警报对话框的响应?,react-native,React Native,据我观察,Alert对话框似乎构建在React本机应用程序之上。 因此,每次调用它时,它都会弹出,而不必出现在render函数中。 问题是,它不是异步任务,因此无论回调函数如何,Alert之后的代码都将继续执行 下面的代码演示了一种情况,警报对话框不断弹出,因为它反复读取相同的条形码。 (这是用TypeScript写的。相信我的话,这是一个有效的代码片段。) import*as React from“React”; 从“反应本机摄影机”导入摄影机; 从“react native”导入{Alert
Alert
对话框似乎构建在React本机应用程序之上。
因此,每次调用它时,它都会弹出,而不必出现在render
函数中。问题是,它不是异步任务,因此无论回调函数如何,
Alert
之后的代码都将继续执行
下面的代码演示了一种情况,警报
对话框不断弹出,因为它反复读取相同的条形码。(这是用TypeScript写的。相信我的话,这是一个有效的代码片段。)
import*as React from“React”;
从“反应本机摄影机”导入摄影机;
从“react native”导入{Alert};
导出默认类BarcodeScanSreen扩展React.Component{
私人摄像机;
private\u onBarCodeRead=e=>{
如果(例如,类型==“QR\U代码”){
警惕,警惕(
“检测到QRCode”,
“您想运行QRCode吗?”,
[
{text:“No”,onPress:this.\u onNoPress},
{文本:“是”,onPress:this.\u onYesPress}
],
{可取消:false}
);
}
};
private _onYesPress=()=>{/*处理QRCode*/}
private _onNoPress=()=>{/*关闭警报对话框。*/}
render(){
返回(
(这个。_camera=ref)}
>
{/*相机预览上方的一些其他组件…*/}
);
}
}
是否有办法暂停JS代码并等待来自
警报的响应?警报不会暂停代码。在这种情况下,JS不是唯一的问题,Camera
组件也会在本机后台运行,它会触发onBarCodeRead
侦听器,无论警报是否存在
您可以尝试使用中提到的stopReview()
方法在\u onBarCodeRead
的开头停止摄像头
还请注意,react native camera
当前正在从camera
(RCTCamera
)迁移到RNCamera
,在新的RNCamera
中,我没有看到stopReview()
方法。无论如何,一个简单的标志也可以完成这项工作。React native Alert不会停止下面代码的执行。通过将其更改为async函数,该函数解析用户操作的承诺,将作为异步警报工作
const AsyncAlert=async()=>新承诺((解析)=>{
警惕,警惕(
“信息”,
"讯息",,
[
{
文本:“ok”,
onPress:()=>{
决定(“是”);
},
},
],
{可取消:false},
);
});
等待AsyncAlert()代码>使用
我刚刚发布了一个软件包,它可以做到这一点,并允许等待用户的选择。它与世博会兼容
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();
}
}
原始答案:我已经为ReactNative做了一个PR,用于此功能:如果您有如下警报功能,我有一些解决方法
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();
此代码不会等待警报响应,它将立即执行refreshPage()
所以,你可以这样做
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 },
);
为此,我喜欢使用两个小型实用程序函数,循环/休眠直到满足某些条件。使用wait
调用它,以阻止执行并将条件作为函数提供
除了警报之外,您还可以使用它来等待其他条件
export function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
export async function until(fn, ms=10) {
while (!fn()) await sleep(ms)
}
这样使用:
choice = false
Alert.alert(
"Delete?",
"", [
{ text: 'Cancel, onPress: () => { choice = 'cancel' }, style: 'cancel' },
{ text: 'OK', onPress: () => { choice = 'ok' } }
],
{ onDismiss: () => { choice = 'cancel' }}
)
await until(() => choice)
if (choice === 'ok') {
...
}
这里有一个简单的解决方案
这里使用的技巧是创建一个调用按钮的onPress
函数的函数,然后使用按钮的索引解析承诺。请注意,这要求警报不可取消
showAsyncAlert=(标题、消息、按钮、选项)=>{
返回新承诺((解决、拒绝)=>{
//我们无法检测到取消,因此请确保警报不可取消。
options.cancelable=false
按钮。forEach((按钮,索引)=>{
让onPress=button.onPress
button.onPress=选项=>{
如果(按下){
onPress(选件)
}
解析(索引)
}
})
警报。警报(标题、消息、按钮、选项)
})
}
最简单的方法是在警报显示时存储一个标志,在警报解除时将其重置为false。我也有类似的想法。但是onBarCodeRead
函数仍然在后台持续运行以检查标志。我想知道是否有更好的方法来处理这个问题。嘿,我刚刚编辑了我的答案,因为我发表了是的,我也有同样的问题<代码>StopReview()
在RNCamera
模块中不推荐使用。我注意到,有时警报
会在RNCamera
中检测到对象时中断,因此在关闭对话框后条形码扫描功能完全停止。当我尝试为react naviagtion navbar构建自定义下拉菜单时,再次陷入此问题。我会尝试一下,谢谢一个非常棒的@SebastienLorber。你的包裹帮了我很多忙!非常感谢。你认为这样更好吗?是的。已测试。“等待仅在异步函数中有效”,这是最近更改的吗?大多数答案都显示了类似的情况,但这些代码示例都没有实际运行。我相信,需要将wait封装在它自己的异步函数中。我最终得到了一个函数,在该函数中,我在Promise中显示了我的警报,onPress
回调正在调用resolve
。谢谢你的灵感
choice = false
Alert.alert(
"Delete?",
"", [
{ text: 'Cancel, onPress: () => { choice = 'cancel' }, style: 'cancel' },
{ text: 'OK', onPress: () => { choice = 'ok' } }
],
{ onDismiss: () => { choice = 'cancel' }}
)
await until(() => choice)
if (choice === 'ok') {
...
}