如何在 React Native 中检测用户离开屏幕并采取相应措施

Joh*_*art 6 navigation alert react-native

如何检测用户在 React Native 中离开屏幕并采取相应行动?

\n

例如,当用户尝试离开当前屏幕时,应弹出警报并说You have unsaved changes, are you sure you want to leave?。用户是否yes可以离开屏幕,no用户是否应该在同一屏幕中。

\n
import { useFocusEffect } from \'@react-navigation/native\';\nimport {Alert} from \'react-native\'\n\nconst Profile = (props) => {\n  useFocusEffect(\n    React.useCallback(() => {\n      // Do something when the screen is focused\n\n      return () => {\n        // Do something when the screen is unfocused\n        // Useful for cleanup functions\n        Alert.alert(\n          \'Want to leave\',\n          \'You have unsaved changes, are you sure you want to leave?\',\n          [\n            {\n              text: \'yes\',\n              onPress: () => {\n                // should leave to the screen user has navigate\n              },\n            },\n            { text: \'no\', onPress: () => null },\n          ],\n          true\n        )\n      };\n    }, [])\n  );\n\n  return <ProfileContent />;\n}\n\nexport default Profile\n
Run Code Online (Sandbox Code Playgroud)\n

目前我在使用这段代码时遇到了一些问题。

\n
    \n
  1. Alert一旦用户已经导航到选定的导航屏幕,就会弹出。但我想Alert在用户导航到所选屏幕之前弹出。

    \n
  2. \n
  3. 如果用户选择否,则用户应保留在同一屏幕中。

    \n
  4. \n
\n

有没有办法实现这些目标?

\n

谢谢。

\n

回答

\n
function EditText({ navigation }) {\n  const [text, setText] = React.useState(\'\');\n  const hasUnsavedChanges = Boolean(text);\n\n  React.useEffect(\n    () =>\n      navigation.addListener(\'beforeRemove\', (e) => {\n        if (!hasUnsavedChanges) {\n          // If we don\'t have unsaved changes, then we don\'t need to do anything\n          return;\n        }\n\n        // Prevent default behavior of leaving the screen\n        e.preventDefault();\n\n        // Prompt the user before leaving the screen\n        Alert.alert(\n          \'Discard changes?\',\n          \'You have unsaved changes. Are you sure to discard them and leave the screen?\',\n          [\n            { text: "Don\'t leave", style: \'cancel\', onPress: () => {} },\n            {\n              text: \'Discard\',\n              style: \'destructive\',\n              // If the user confirmed, then we dispatch the action we blocked earlier\n              // This will continue the action that had triggered the removal of the screen\n              onPress: () => navigation.dispatch(e.data.action),\n            },\n          ]\n        );\n      }),\n    [navigation, hasUnsavedChanges]\n  );\n\n  return (\n    <TextInput\n      value={text}\n      placeholder="Type something\xe2\x80\xa6"\n      onChangeText={setText}\n    />\n  );\n}\n
Run Code Online (Sandbox Code Playgroud)\n

有关更多信息,请参阅:https://reactnavigation.org/docs/preventing-going-back/

\n

这将防止用户从一个屏幕返回到另一屏幕。但这并不会阻止选项卡导航,因为屏幕不会被删除。

\n

防止选项卡导航

\n
<Tab.Screen\n                    name={\'search\'}\n                    component={SearchNavigator}\n                    options={{\n                      tabBarIcon: ({ focused, color }) => (\n                        <View>\n                          <Icon\n                            name=\'search1\'\n                            color={\n                              focused\n                                ? \'black\'\n                                : \'white\'\n                            }\n                            size={25}\n                          />\n                        </View>\n                      ),\n                    }}\n                    listeners={{\n                      tabPress: (e) => {\n                        if (true) {\n                          // Prevent default action\n                          e.preventDefault()\n                          // Prompt the user before leaving the screen\n                          Alert.alert(\n                            \'Discard changes?\',\n                            \'You have unsaved changes. Are you sure to discard them and leave the screen?\',\n                            [\n                              {\n                                text: "Don\'t leave",\n                                style: \'cancel\',\n                                onPress: () => {},\n                              },\n                              {\n                                text: \'Discard\',\n                                style: \'destructive\',\n                                // If the user confirmed, then we dispatch the action we blocked earlier\n                                // This will continue the action that had triggered the removal of the screen\n                                onPress: () =>\n                                  navigationRef.current?.navigate(\n                                    \'search\',\n                                    {}\n                                  ),\n                              },\n                            ]\n                          )\n                        }\n                      },\n                    }}\n                  />\n
Run Code Online (Sandbox Code Playgroud)\n

您可以像上面的代码一样添加侦听器tabPress并提供警报。

\n