React native 背面的确认/警告对话框
就像在web浏览器中一样,我们使用onBeforeUnload(vs onUnload)来显示警报或一些警告:“有未保存的数据-您确定要返回吗?” 我也试着这么做。我在react navigation的文档中找不到任何东西 我曾想过做一些像这样的粗俗的事情,但我不知道这样做是否正确:React native 背面的确认/警告对话框,react-native,react-navigation,React Native,React Navigation,就像在web浏览器中一样,我们使用onBeforeUnload(vs onUnload)来显示警报或一些警告:“有未保存的数据-您确定要返回吗?” 我也试着这么做。我在react navigation的文档中找不到任何东西 我曾想过做一些像这样的粗俗的事情,但我不知道这样做是否正确: import React, { Component } from 'react' import { StackNavigator } from 'react-navigation' export default
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} /> );
}
}
}
import React,{Component}来自“React”
从“反应导航”导入{StackNavigator}
导出默认函数ConfirmBackStackNavigator(路由、选项){
const StackNav=StackNavigator(路线、选项);
返回类ConfirmBackStackNavigatorComponent扩展组件{
静态路由器=StackNav.router;
render(){
const{state,goBack}=this.props.navigation;
常数导航={
…这个.props.navigation,
戈巴克:()=>{
showConfirmDialog()
.then(didConfirm=>didConfirm&&goBack(state.key))
}
};
返回();
}
}
}
这可以通过在标题中显示一个自定义后退按钮来完成,并在硬件后退事件出现在导航器之前捕获它
我们将首先通过覆盖导航选项将页面配置为显示自定义后退按钮:
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 }
}
// ...
}
在当前屏幕集上
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);
};
注意,
在没有导航道具的情况下导航
NavigationService.js
function dispatch(...args) {
_navigator.dispatch(...args);
}
React navigation 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}
/>
);
}
函数EditText({navigation}){
const[text,setText]=React.useState(“”);
const hasUnsavedChanges=布尔值(文本);
反作用(
() =>
navigation.addListener('beforeRemove',(e)=>{
如果(!hasUnsavedChanges){
//如果没有未保存的更改,则无需执行任何操作
返回;
}
//防止离开屏幕的默认行为
e、 预防默认值();
//在离开屏幕前提示用户
警惕,警惕(
“放弃更改吗?”,
'您有未保存的更改。是否确实要放弃这些更改并离开屏幕?',
[
{文本:“不要离开”,样式:“取消”,按:()=>{},
{
文本:“放弃”,
风格:“破坏性”,
//如果用户确认了,那么我们将发送先前阻止的操作
//这将继续触发删除屏幕的操作
onPress:()=>navigation.dispatch(例如,data.action),
},
]
);
}),
[导航,更改]
);
返回(
);
}
Doc:这也在他们的问题追踪者上进行了讨论:感谢@LinusUnnebäck分享这些链接!如果我们做了几个步骤的编程,而这是堆栈中的一个页面,那么这就行不通了。你介意详细说明这个问题吗?你的意思是如果你已经离开了页面,然后一步弹出多个页面吗?当然谢谢你的提问。屏幕1转到屏幕2。屏幕2背面有警告。然而,从屏幕2我们打开屏幕3(例如模式)。在屏幕3中,我们执行
goBack(…)
或poptoop()
,以便返回到屏幕1。它应该返回到屏幕2,并显示警告,如果同意,它应该继续返回到屏幕1。
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}
/>
);
}