React-Native:按下 android 硬件后退按钮返回
Posted
技术标签:
【中文标题】React-Native:按下 android 硬件后退按钮返回【英文标题】:React-Native: Go back on android hardware back button pressed 【发布时间】:2017-01-19 15:23:21 【问题描述】:我正在尝试在按下 android 后退按钮时添加返回 webview,但我仍然无法使其工作。
这是我的代码:
<WebView
ref=WEBVIEW_REF
source=source
domStorageEnabled=true
onNavigationStateChange=this.onNavigationStateChange
/>
componentDidMount()
BackAndroid.addEventListener('hardwareBackPress', function()
if(this.state.backButtonEnabled)
this.refs[WEBVIEW_REF].goBack();
return true;
);
;
onNavigationStateChange = (navState) =>
this.setState(
backButtonEnabled: navState.canGoBack,
);
;
使用上面的代码,我得到错误 undefined is not an object this.state.backButtonEnabled(在状态中设置)。
我只是想看看 goBack 是否有效,所以我删除了 if 语句,然后我得到错误 undefined is not an object this.refs[WEBVIEW_REF]。
什么是最好的解决方案?
【问题讨论】:
如果在render方法中抛出backandroid事件监听器会怎样? 我遇到了同样的错误。 【参考方案1】:想添加一个完整的例子,以防它帮助任何人:
import React, Component from 'react';
import
BackHandler,
Platform,
WebView,
from 'react-native';
class ExampleWebView extends Component
webView =
canGoBack: false,
ref: null,
onAndroidBackPress = () =>
if (this.webView.canGoBack && this.webView.ref)
this.webView.ref.goBack();
return true;
return false;
componentWillMount()
if (Platform.OS === 'android')
BackHandler.addEventListener('hardwareBackPress', this.onAndroidBackPress);
componentWillUnmount()
if (Platform.OS === 'android')
BackHandler.removeEventListener('hardwareBackPress');
render()
return (
<WebView
source= uri: "https://www.google.com"
ref=(webView) => this.webView.ref = webView;
onNavigationStateChange=(navState) => this.webView.canGoBack = navState.canGoBack;
/>
);
【讨论】:
这是一个全面的解决方案。也许你应该创建一个要点? 出现错误 - TypeError: TypeError: undefined is not an object (evalating '_this2.webView.ref = webView') 我想需要绑定onAndroidBackPress
?
@Crisfole 如果您使用箭头函数,就像我在此处的示例中使用的那样。
我很确定还有一些额外的复杂性,尤其是在事件绑定方面。不过我可能是错的。 javascriptweblog.wordpress.com/2015/11/02/…【参考方案2】:
class MyComponent extends Component
state = ;
componentDidMount()
BackHandler.addEventListener('hardwareBackPress', this.backHandler);
componentWillUnmount()
BackHandler.removeEventListener('hardwareBackPress', this.backHandler);
backHandler = () =>
if(this.state.backButtonEnabled)
this.refs[WEBVIEW_REF].goBack();
return true;
1) 绑定你的处理程序 2) 不要忘记在卸载时删除监听器。
【讨论】:
我确实在 5 分钟前修复了它,这实际上也是我所做的 :) 仍然感谢您的帮助,我肯定也会帮助其他开发人员! BackAndroid 将被弃用,最好使用 BackHandler 像 @RamRovi 回答【参考方案3】:这是一个带有 Typescript 和 useRef
和 useEffect
钩子的解决方案。
我没有使用canGoBack
,但它似乎无论如何都可以工作。
import React, useEffect, useRef from 'react';
import BackHandler from 'react-native';
import WebView from 'react-native-webview';
const WebViewWrapper = (): JSX.Element =>
const webview = useRef<WebView>(null);
const onAndroidBackPress = (): boolean =>
if (webview.current)
webview.current.goBack();
return true; // prevent default behavior (exit app)
return false;
;
useEffect((): (() => void) =>
BackHandler.addEventListener('hardwareBackPress', onAndroidBackPress);
return (): void =>
BackHandler.removeEventListener('hardwareBackPress', onAndroidBackPress);
;
, []); // Never re-run this effect
return (
<WebView
source= uri: 'https://***.com'
ref=webview
/>
)
【讨论】:
这条线帮助了我return true; // prevent default behavior (exit app)
。【参考方案4】:
这可能对某人有所帮助,因为上述解决方案没有解决我的问题....
import React, Component from 'react';
import
BackHandler,
WebView,
from 'react-native';
export default class App extends Component
constructor(props)
super(props);
this.WEBVIEW_REF = React.createRef();
componentDidMount()
BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
componentWillUnmount()
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
handleBackButton = ()=>
this.WEBVIEW_REF.current.goBack();
return true;
onNavigationStateChange(navState)
this.setState(
canGoBack: navState.canGoBack
);
render()
return (
<WebView
source= uri: "https://www.cbt.ng"
ref=this.WEBVIEW_REF
onNavigationStateChange=this.onNavigationStateChange.bind(this)
/>
)
【讨论】:
【参考方案5】:如果您正在寻找functional component
解决方案。
注意:执行返回操作不需要canGoBack状态,它只是为了保存当前状态,你可以放心删除它
import React, useState, useEffect, useRef from "react"
import BackHandler, Platform from "react-native"
import SafeAreaView from "react-navigation"
import WebView from "react-native-webview"
const Webview = () =>
const webView = useRef(null);
const [canGoBack, setCanGoBack] = useState(false);
useEffect(() =>
if (Platform.OS === 'android')
BackHandler.addEventListener('hardwareBackPress', HandleBackPressed);
return () =>
BackHandler.removeEventListener('hardwareBackPress', HandleBackPressed);
, []); // INITIALIZE ONLY ONCE
const HandleBackPressed = () =>
if (webView.current)
webView.current.goBack();
return true; // PREVENT DEFAULT BEHAVIOUR (EXITING THE APP)
return false;
return (
<SafeAreaView>
<WebView
ref=webView
source=
uri: "<YOUR_URL>"
onNavigationStateChange=navState => setCanGoBack(navState.canGoBack)
/>
</SafeAreaView>
)
export default Webview;
【讨论】:
请不要使用状态来维护canGoBack,因为改变状态会导致重新渲染,而是使用refs 嘿,这是可行的,但是从应用程序中,我们无法在按下后退按钮时退出,就像在家里我们按下后退一样,所以它应该退出但它没有退出应用程序 历史长度不小于2才会退出应用【参考方案6】:不幸的是,onNavigationStateChange
没有为 SPA(单页应用程序)网站触发:https://github.com/react-native-webview/react-native-webview/issues/1510
改用onLoadProgress
:
import React, useRef, useState, useCallback, useEffect from "react";
import BackHandler from "react-native";
import WebView from "react-native-webview";
export default function App()
const webView = useRef();
const [canGoBack, setCanGoBack] = useState(false);
const handleBack = useCallback(() =>
if (canGoBack && webView.current)
webView.current.goBack();
return true;
return false;
, [canGoBack]);
useEffect(() =>
BackHandler.addEventListener("hardwareBackPress", handleBack);
return () =>
BackHandler.removeEventListener("hardwareBackPress", handleBack);
;
, [handleBack]);
return (
<WebView
ref=webView
source= uri: "https://my-awesome-spa.com/"
onLoadProgress=(event) => setCanGoBack(event.nativeEvent.canGoBack)
/>
);
【讨论】:
感谢您的回答。它对我有用......【参考方案7】:在 react native 中的 webview 的情况下,默认情况下按下移动端的后退按钮时应用程序退出。如果你想在按下返回按钮的时候回到上一页,那么你需要实现react-native webview的“返回”功能。
您可以查看本文的Step 5 : Handle Mobile Back Button部分。
【讨论】:
【参考方案8】:添加到@Nisharg Shah 答案。对于onNavigationStateChange
道具,添加以下行
onNavigationStateChange=navState => webView.current.canGoBack = navState.canGoBack
在HandleBackPressed
方法中检查webView.current.canGoBack
然后webView.current.goBack();
否则return false
import React, useState, useEffect, useRef from "react"
import BackHandler, Platform from "react-native"
import SafeAreaView from "react-navigation"
import WebView from "react-native-webview"
const Webview = () =>
const webView = useRef(null);
const [canGoBack, setCanGoBack] = useState(false);
useEffect(() =>
if (Platform.OS === 'android')
BackHandler.addEventListener('hardwareBackPress', HandleBackPressed);
return () =>
BackHandler.removeEventListener('hardwareBackPress', HandleBackPressed);
, []); // INITIALIZE ONLY ONCE
const HandleBackPressed = () =>
if (webView.current.canGoBack)
webView.current.goBack();
return true; // PREVENT DEFAULT BEHAVIOUR (EXITING THE APP)
return false;
return (
<SafeAreaView>
<WebView
ref=webView
source=
uri: "<YOUR_URL>"
onNavigationStateChange=navState => webView.current.canGoBack = navState.canGoBack ->> This line is important
/>
</SafeAreaView>
)
export default Webview;
【讨论】:
【参考方案9】:所有功能组件的答案都有缺陷(比如当webview无法返回时无法使用返回按钮退出应用程序)。
这与最受好评的基于类的答案的行为相同:
import React, useEffect, useRef, useState from 'react';
import BackHandler, Platform from 'react-native';
import WebView from 'react-native-webview';
const App = () =>
const webview = useRef<WebView>(null);
const [canGoBack, setCanGoBack] = useState(false);
const onAndroidBackPress = () =>
if (canGoBack && webview.current)
webview.current.goBack();
return true;
return false;
useEffect(() =>
if (Platform.OS === 'android')
BackHandler.addEventListener('hardwareBackPress', onAndroidBackPress);
return () =>
BackHandler.removeEventListener('hardwareBackPress', onAndroidBackPress);
, [canGoBack]);
return (
<WebView
source=uri: 'https://www.google.com'
ref=webview
onNavigationStateChange=(navState) => setCanGoBack(navState.canGoBack)
/>
);
;
export default App;
【讨论】:
以上是关于React-Native:按下 android 硬件后退按钮返回的主要内容,如果未能解决你的问题,请参考以下文章