I am trying to add going back on webview when the android backbutton was pressed and I still couldn't manage to make it work.
This is my code:
<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,
});
};
With the code above I'm getting the error undefined is not an object this.state.backButtonEnabled (which is set in the state).
Than I just wanted to see if the goBack works so I removed the if statement and than I was getting the error undefined is not an object this.refs[WEBVIEW_REF].
What is the best solution for this?
To handle the Android Back Button Press in the React Native we have to register the hardwareBackPress event listener with a callback function, which will be called after pressing the Back Button.
The addEventListener takes in a callback function as its second parameter. The callback function is triggered when the event we are listening to occurs (hardware back button press).
Wanted to add a full example in case it helps anyone:
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; }}
/>
);
}
}
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) Bind your handler 2) Do not forget to removeListener on unmount.
Here's a solution with Typescript and useRef
and useEffect
hooks.
I didn't use canGoBack
, but it seems to work regardless.
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://stackoverflow.com' }}
ref={webview}
/>
)
}
This might help someone as the above solutions didn't solve my problem....
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)}
/>
)
}
}
If you are looking for a functional component
solution.
Note: canGoBack state is not required for performing back operation, it's just to save the current state, you can safely remove it if you want
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With