Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confirm/warn dialog on back

Like in the web browser, we have onBeforeUnload (vs onUnload) to show a alert or some warning "there is unsaved data - are you sure you want to go back".

I am trying to do the same. I couldn't find anything in the docs of react-navigation.

I thought of doing something real hacky like this, but I don't know if its the right way:

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} /> );
        }
    }
}
like image 273
Noitidart Avatar asked Jan 03 '23 12:01

Noitidart


1 Answers

React navigation 5.7 has added support for it:

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

Doc: https://reactnavigation.org/docs/preventing-going-back

like image 152
chengsam Avatar answered Jan 05 '23 14:01

chengsam