在React应用中拦截返回事件以确认保存

时间:2019-06-05 19:58:37

标签: reactjs react-native react-navigation expo

我正在使用expo.io构建一个React Native应用程序。

该应用程序正在使用Stack Navigator在页面(卡片)之间移动。

我的问题是我有一个页面,用户可以在其中创建新项目,并且我想在离开页面时保存这些项目。 除了保存所有更改之外,我想提示用户是否要在离开页面之前保存更改,以便他们有机会放弃所做的任何更改。

我无法找到退出该页面的事件并提示用户是否要保存更改? 我发现与我想做的最接近的是backhandler,但这仅适用于Android后退按钮。

如果用户使用卡头中的“后退”按钮返回,或者使用轻扫手势,是否可以执行类似的操作?

2 个答案:

答案 0 :(得分:1)

使用NavigationEvents。将事件侦听器添加到您的组件中。

  

onWillFocus-事件监听器

     

onDidFocus-事件监听器

     

onWillBlur-事件侦听器

     

onDidBlur-事件侦听器

例如,当下一个屏幕聚焦时,将触发以下内容:在另一个屏幕中,将用户的更改保存到临时存储中,当他们向后导航时,获取那些未保存的更改并提示用户是否要保存或不。

focusSubscription = null;

onWillFocus = (payload) => {

  if (payload && payload.action && payload.action.type && payload.action.type === 'Navigation/BACK') {

    // get values from storage here
    // if there were unsaved changes prompt the user if they want to those changes or not
  }
};

componentDidMount = () => {

  this.focusSubscription = this.props.navigation.addListener(
    'willFocus',
    this.onWillFocus,
  );
 }

componentWillUnmount = () => {
  this.focusSubscription && this.focusSubscription.remove();
  this.focusSubscription = null;
};

Demo

答案 1 :(得分:0)

React Navigation 在 5.7 版中添加了您可以使用的 beforeRemove 事件。

这是他们网站上的演示:

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