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

时间:2018-02-15 14:37:24

标签: react-native

根据我的观察,Alert对话框似乎建立在React Native应用程序之上。 因此,每当您调用它时它就会弹出,而不会出现在render函数中 问题是它不是异步任务,因此无论回调函数如何,Alert之后的代码都将继续执行。

下面的代码演示了Alert对话框不断弹出的情况,因为它一遍又一遍地读取相同的条形码。
(它是用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的响应?

6 个答案:

答案 0 :(得分:5)

使用react-native-alert-async

我刚刚发布了一个软件包,该软件包正是这样做的,并允许等待用户的选择。它与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();
   }

 }

原始答案:我为此功能向ReactNative做了PR:https://github.com/facebook/react-native/pull/20312

答案 1 :(得分:2)

React-native Alert不会停止执行其下面的代码。通过将其更改为异步功能,可以解决对用户操作的承诺,将作为ASYNC-Alert。

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

await AsyncAlert();

答案 2 :(得分:1)

警报不会暂停代码。在这种情况下,JS不是唯一的问题 - Camera组件也在后台继续运行,它是本机的,它将触发onBarCodeRead侦听器,无论警报是否存在。

您可以尝试使用docs中提到的_onBarCodeRead方法在stopPreview()处开始停止相机。

另请注意,react-native-camera目前正处于从CameraRCTCamera)到RNCamera的迁移过程中以及新RNCamera中的stopPreview()。请参阅x.set_index('b').a.str.get_dummies(sep=',').replace(0,np.nan).stack().reset_index().drop(0,1) Out[481]: b level_1 0 1 y 1 1 x 2 0 r 3 0 t 4 0 x 5 0 x 6 1 t 7 1 y 方法。无论如何,一个简单的旗帜也可以完成这项任务。

答案 3 :(得分:1)

这是一个简单的解决方案。

这里使用的技巧是使一个函数调用按钮的void wavelet_tree_to_stream(std::ostream& to, const wavelet_tree* node) { to << "{" to << "\"alphabet\":\"" << node->alphabet << "\""; to << ','; to << "\"middle\": \"" << node->middle << "\""; if(nullptr != node->Left) { to << ",\"Left\" : "; wavelet_tree_to_stream(to, node->Left); } if(nullptr != node->Right) { to << ",\"Right\" : "; wavelet_tree_to_stream(to, node->Right); } to << "}"; } ...... wavelet_tree_to_stream(fstream, root); 函数,然后使用按钮的索引来解决promise。请注意,这要求警报不可取消。

onPress

用法:

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

答案 4 :(得分:0)

我对此有一些解决方法,如果您具有以下警报功能

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

答案 5 :(得分:0)

为此,我喜欢使用两个小的实用程序函数,它们会循环/休眠直到满足某些条件。用script调用它以阻止执行并将条件作为函数提供。

除了带有警报,您还可以使用它来等待其他情况。

await

像这样使用:

export function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms))
}

export async function until(fn, ms=10) {
  while (!fn()) await sleep(ms)
}