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') {
    ...
}