确认/警告对话框

时间:2018-04-19 19:05:47

标签: react-native react-navigation

就像在网络浏览器中一样,我们有onBeforeUnload(vs onUnload)来显示警告或警告“有未保存的数据 - 你确定要回去”。

我正在努力做同样的事情。我在react-navigation的文档中找不到任何内容。

我想做一些像这样的真正hacky,但我不知道它是否正确:

import React, { Component } from 'react'
import { StackNavigator } from 'react-navigation'


export default function ConfirmBackStackNavigator(routes, options) {
    const StackNav = StackNavigator(routes, options);

    return class ConfirmBackStackNavigatorComponent extends Component {
        static router = StackNav.router;

        render() {
            const { state, goBack } = this.props.navigation;

            const nav = {
                ...this.props.navigation,
                goBack: () => {
                    showConfirmDialog()
                    .then(didConfirm => didConfirm && goBack(state.key))
                }
            };
            return ( <StackNav navigation = {nav} /> );
        }
    }
}

4 个答案:

答案 0 :(得分:1)

在当前屏幕设置上

this.props.navigation.setParams({
  needUserConfirmation: true,
});

在您的堆栈中

const defaultGetStateForAction = Stack.router.getStateForAction;
Stack.router.getStateForAction = (action, state) => {
  if (state) {
    const { routes, index } = state;
    const route = get(routes, index);
    const needUserConfirmation = get(route.params, 'needUserConfirmation');
    if (
      needUserConfirmation &&
      ['Navigation/BACK', 'Navigation/NAVIGATE'].includes(action.type)
    ) {
      Alert.alert('', "there is unsaved data - are you sure you want to go back", [
        {
          text: 'Close',
          onPress: () => {},
        },
        {
          text: 'Confirm',
          onPress: () => {
            delete route.params.needUserConfirmation;
            state.routes.splice(index, 1, route);
            NavigationService.dispatch(action);
          },
        },
      ]);
      // Returning null from getStateForAction means that the action
      // has been handled/blocked, but there is not a new state
      return null;
    }
  }

  return defaultGetStateForAction(action, state);
};

注意, 在没有导航道具的情况下进行导航 https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html

NavigationService.js

function dispatch(...args) {
  _navigator.dispatch(...args);
}

答案 1 :(得分:1)

反应导航5.7添加了对此的支持:

function EditText({ navigation }) {
  const [text, setText] = React.useState('');
  const hasUnsavedChanges = Boolean(text);

  React.useEffect(
    () =>
      navigation.addListener('beforeRemove', (e) => {
        if (!hasUnsavedChanges) {
          // If we don't have unsaved changes, then we don't need to do anything
          return;
        }

        // Prevent default behavior of leaving the screen
        e.preventDefault();

        // Prompt the user before leaving the screen
        Alert.alert(
          'Discard changes?',
          'You have unsaved changes. Are you sure to discard them and leave the screen?',
          [
            { text: "Don't leave", style: 'cancel', onPress: () => {} },
            {
              text: 'Discard',
              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, hasUnsavedChanges]
  );

  return (
    <TextInput
      value={text}
      placeholder="Type something…"
      onChangeText={setText}
    />
  );
}

文档:https://reactnavigation.org/docs/preventing-going-back

答案 2 :(得分:-1)

这可以通过在标题中显示一个自定义后退按钮,并在硬件后退事件导航到导航器之前捕获它来完成。

我们将首先通过覆盖导航选项将页面配置为显示自定义后退按钮:

import React, { Component } from 'react'
import { Button } from 'react-native'

function showConfirmDialog (onConfirmed) { /* ... */ }

class MyPage extends Component {
  static navigationOptions ({ navigation }) {
    const back = <Button title='Back' onPress={() => showConfirmDialog(() => navigation.goBack())} />

    return { headerLeft: back }
  }

  // ...
}

下一步是覆盖硬件后退按钮。为此,我们将使用软件包react-navigation-backhandler

// ...
import { AndroidBackHandler } from 'react-navigation-backhandler'

class MyPage extends Component {
  // ...

  onHardwareBackButton = () => {
    showConfirmDialog(() => this.props.navigation.goBack())
    return true
  }

  render () {
    return (
      <AndroidBackHandler onBackPress={this.onHardwareBackButton}>
        {/* ... */}
      </AndroidBackHandler>
    )
  }
}

答案 3 :(得分:-2)

我真的会改变这种方法,在原生中你没有网络的限制,我从来没有看到过这种模式的实现。其他人所做的是他们保存数据并提供一个链接,以便您在以后离开的地方继续。根据您的应用程序,您可以在不同的地方进行,但我真的会看一下平台的导航模式。