如何在React Native中等待Alert对话框的响应?

btxsgosb  于 2023-06-24  发布在  React
关注(0)|答案(7)|浏览(112)

从我的观察来看,Alert对话框似乎构建在React Native应用程序之上。所以每次你调用它的时候它都会弹出,而不是在render函数中。
问题是它不是一个异步任务,所以Alert之后的代码将继续执行,而不管回调函数如何。
下面的代码演示了Alert对话框不断弹出的情况,因为它一遍又一遍地读取相同的条形码。
(It是用TypeScript写的。这是我的一句话,这是一个有效的片段)。

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>
    );
}
}

有没有办法暂停JS代码并等待Alert的响应?

kcrjzv8t

kcrjzv8t1#

React-native Alert不会停止其下代码的执行。通过将其更改为异步函数,解决用户操作的承诺将作为ASYNC-Alert工作。

const AsyncAlert = async () => new Promise((resolve) => {
  Alert.alert(
    'info',
    'Message',
    [
      {
        text: 'ok',
        onPress: () => {
          resolve('YES');
        },
      },
    ],
    { cancelable: false },
  );
});

await AsyncAlert();
nqwrtyyt

nqwrtyyt2#

使用react-native-alert-async

我刚刚发布了一个包,它完全可以做到这一点,并允许等待用户的选择。与世博会兼容。

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();
   }

 }

**原文答案:**我已经为这个功能做了PR给ReactNative:https://github.com/facebook/react-native/pull/20312

rn0zuynd

rn0zuynd3#

这里有一个简单的解决方案。
这里使用的技巧是创建一个调用按钮的onPress函数的函数,然后用按钮的索引解析promise。请注意,这要求警报不可取消。

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)
  })
}

用途:

let option = await showAsyncAlert(title, message, buttons options)

if (option === 0) {
    foo()
} else {
    bar()
}
3df52oht

3df52oht4#

警报不会暂停代码。在这种情况下,JS不是唯一的问题-Camera组件也会在本机的后台运行,它将触发onBarCodeRead监听器,不管Alert是否存在。
您可以尝试使用文档中提到的stopPreview()方法在_onBarCodeRead开始时停止相机。
还要注意的是,react-native-camera目前正在从CameraRCTCamera)迁移到RNCamera,在新的RNCamera中,我没有看到stopPreview()方法。不管怎样,一面简单的旗帜也可以完成这项工作。

ssgvzors

ssgvzors5#

我有一些变通方法,如果你有警报功能,如下面

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();

此代码不会等待alert的响应,它将立即执行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 },
                );
lzfw57am

lzfw57am6#

如果您需要返回Promise:

const asyncAlert = (title, message, callback) => (new Promise((resolve) => {
    Alert.alert(
        title,
        message,
        [{ text: "Cancel" }, { text: "OK", onPress: () => resolve() }], { cancelable: false }
    );
}).then(callback));

用途:

return asyncAlert("My Title", "Are you sure?", () => SOME_PROMISE_FUNCTION())
yhuiod9q

yhuiod9q7#

https://www.npmjs.com/package/react-native-async-alert
使用这个npm。这和上面@Makatun的答案一样,但是简单可靠。

import {AlertProvider} from 'react-native-async-alert';
  import {useShowAlert} from 'react-native-async-alert';

  function App() {
    return (
      <AlertProvider>
        {/* Content */}
      </AlertProvider>
     );
  }

就像这样简单地使用它。您也可以自定义您的警报。

import {useShowAlert} from 'react-native-async-alert';
  const result = await showAlert({
    title: 'Title',
    text: 'text',
  });
  console.log(result);

相关问题