10

React Native WebView App not exit on pressing back button after setting Go back functionality on back button pressed. I want go back functionality on pressing back button when webview is not on home page and when webview is on home page then exit the app.

export default class WebView 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://stackoverflow.com' }}
            ref={this.WEBVIEW_REF}
            onNavigationStateChange={this.onNavigationStateChange.bind(this)}

          />
        );
      }
    }
beginner
  • 331
  • 2
  • 14

2 Answers2

21

Since you are managing the state of canGoBack inside onNavigationStateChange function, Change your handleBackButton function as below,

handleBackButton = () => {
  if (this.state.canGoBack) {
    this.WEBVIEW_REF.current.goBack();
    return true;
  }
}

Check below complete example

import React, { Component } from "react";
import { BackHandler } from "react-native";
import { WebView } from "react-native-webview";

export default class App extends Component {
  WEBVIEW_REF = React.createRef();

  state = {
    canGoBack: false,
  };

  componentDidMount() {
    BackHandler.addEventListener("hardwareBackPress", this.handleBackButton);
  }

  componentWillUnmount() {
    BackHandler.removeEventListener("hardwareBackPress", this.handleBackButton);
  }

  handleBackButton = () => {
    if (this.state.canGoBack) {
      this.WEBVIEW_REF.current.goBack();
      return true;
    }
  };

  onNavigationStateChange = (navState) => {
    this.setState({
      canGoBack: navState.canGoBack,
    });
  };

  render() {
    return (
      <WebView
        source={{ uri: "https://stackoverflow.com" }}
        ref={this.WEBVIEW_REF}
        onNavigationStateChange={this.onNavigationStateChange}
      />
    );
  }
}

Hope this helps you. Feel free for doubts.

SDushan
  • 4,341
  • 2
  • 16
  • 34
  • thank you for the code. this.WEBVIEW_REF.current is throwing null. Help please. – mlg Feb 20 '22 at 16:23
0

I had this problem for quite a while but i have managed to resolve it. Problem that I experienced was that goBack (which is used as back event) function was triggered before onNavigationStateChange but somehow state was change although goBack function was called first.

const HomeScreen = () => {
  const {web} = config;
  const ref = useRef();
  const [canGoBack, setCanGoBack] = useState(false);

  const setupState = event => {
    setCanGoBack(event?.canGoBack);
  };

  useEffect(() => {
    const goBack = () => {
      if (canGoBack === false) {
        Alert.alert(
          'Exit App',
          'Do you want to exit app?',
          [
            {text: 'No', onPress: () => console.log('No'), style: 'cancel'},
            {text: 'Yes', onPress: () => BackHandler?.exitApp()},
          ],
          {cancelable: false},
        );
      }
      ref?.current?.goBack();
      return true;
    };

    BackHandler?.addEventListener('hardwareBackPress', () => goBack());

    return () =>
      BackHandler?.removeEventListener('hardwareBackPress', () => goBack());
  }, [canGoBack]);

  return (
    <View style={styles.mainContainer}>
      {/* last version 11.21.1 */}
      <WebView
        ref={ref}
        source={{uri: web?.url}}
        style={{flex: 1}}
        cacheEnabled={web.cacheEnabled}
        automaticallyAdjustContentInsets={false}
        domStorageEnabled={true}
        startInLoadingState={true}
        allowsInlineMediaPlayback={true}
        allowsBackForwardNavigationGestures
        onNavigationStateChange={e => setupState(e)}
      />
    </View>
  );
};

export default HomeScreen;
koskee
  • 1