supergravity

expo - webview back button 본문

개발중 기억해야 할만한 것들/엑스포, 리액트 네이티브

expo - webview back button

supergravity 2021. 5. 3. 20:59

시작

2021 제주창조경제혁신센터 예비창업패키지 광탈로 계획이 변경되었다.

예비창업패키지 탈락 이유를 이메일로 연락했을 때 씹어서 전화를 했다.

전화로 탈락 이유와 서류통과 커트라인 그리고 나의 점수를 알려 달라고 요청을 했다.

그런데 서류통과 커트라인에 대해서는 전달할 수 없다고 말했다.

 

 

쇼핑몰의 제품을 통해 재방문율을 올릴 계획을 가지고 있었다. 

이 계획은 일단 보류이다. 

대체된 계획인 이렇다. 

지속적으로 방문을 유도하기 위하여 레시피 정보를 제공하는 게시판을 만드는 것!

그리고 공모전이나 인턴에 지원을 하는 것...... ㅅㅂ

 

무슨 방법으로 게시판을 만들까?

티스토리를 expo의 webview를 이용하여 만들 계획이다. 

그리고 차후에 아이엠웹 플랫폼을 이용하여 쇼핑몰까지 추가할 것이다. 

코딩은 인생 낭비이다... 최대한 적게 하자

 

하지만 문제점이 있다. 그것은 바로  back button이다.

현재 사용하는 bottom teb의 경우는 react-navigation로 작성되었다. 

그래서 webview로 제공되는 webpage의 backbutton을 react-navigation과 같은 시스템으로 구성해야 한다. 

그리고 통합해야 한다. 

 

그러면 back button을 공부하고 구현해 보자. 

 

구현

WEBVIEW.current.goBack() 함수와  react nativa에서 기본으로 제공하는 BackHandler를 이용하여 구현하면 된다. 

 

1.0 expo WebView

NOTE : 참고로 WebView는 웹에서 사용이 불가능하다. 디버그를 web으로 하는 사람이라면 다른 방법을 찾아 야한다.

 

expo install react-native-webview

 

일단 shell에 위의 명령어를 적어보자. (우리는 코드 몽키?)

 

webView의 probs인 ref를 이용하면 웹 페이지의 정보와 javascript 코드를 삽입할 수 있다.

이글에서는 javascript의 코드를 삽입하는 일은 하지 않을 것이다. 궁금하면 아래의 링크로 들어가서 읽으면 된다

github.com/react-native-webview/react-native-webview/blob/master/docs/Guide.md#react-native-webview-guide

 

react-native-webview/react-native-webview

React Native Cross-Platform WebView. Contribute to react-native-webview/react-native-webview development by creating an account on GitHub.

github.com

우선 ref의 consol.log를 처보자.

 

<WebView
          ref={(r) => consol.log(r.current)}
          source={{
            uri: 'https://github.com/react-native-webview/react-native-webview',
          }}
        />
      </View>

그러면 졸라게 많이 출력이 된다. 

 

현재 페이지, 이전 폐지, 다음 페이지, goback() etc......

여기서 우리는 이전 페이지와 goBack()을 사용할 것이다. 

 

이전 페이지의 주소와 goBack() 함수를 기존의 react-navigation 시스템과 동일하게 구현하면 끝!

 

2.0 expo BackHandler

2.1 핸들러가 뭔데??? 손으로 장난치는 건가?? 나의 오른손? 소름

 

제목에서 핸들러란 단어는 무엇을 의미할까???

핸들러 개념이 살라면 쓰래드의 개념부터 알고 가야 한다. 

 

일단 쓰래드는 프로세스 내에 존재하는 실행 코드 들이다. 

이게 무슨 말이냐?? 코더가 작성한 실행 코드들이란 것!

결국 다이내믹하지 못하다. 

역사적으로 쓰래드의 다이내믹함을 추가하기 위하여 핸들러를 만들었다.

아래의 그림을 보자.  

 

 

 

그렇다면 BackHandler는 뒤로 가기 버튼으로부터 정보를 수신하고 특정 쓰래드를 변경시키는 역할을 한다. 

 

2.1 본격적인 BackHandler 

핸들러는 신호를 기다리다 신호가 오면 쓰래드에 정보를 전달한다.

고맙게 도 위의 기능을 전부 expo에서 구현해 주었다.

인생 낭비하지 말고 남이 한 거 쓰자

 

docs.expo.io/versions/latest/react-native/backhandler/

 

BackHandler - Expo Documentation

Expo is an open-source platform for making universal native apps for Android, iOS, and the web with JavaScript and React.

docs.expo.io

BackHandler.addEventListener('hardwareBackPress', backAction);

이함 수를 이용하면 핸들러를 시작할 수 있다. 

이 함수 이후의 시간은 핸들러가 하드웨어뒤누름 신호를 기다리게 된다.

 

BackHandler.removeEventListener("hardwareBackPress", backHandler);

시간이 지나 하드웨어뒤누름 신호를 받았으면 실행시킨 백버튼을 위의 코드를 이용하여 삭제해줘야 한다. 

 

NOTR:

신호를 삭제하는 것에 대해서 납득이 안 되는 분들이 있는데....

삭제를 안 할 때를 생각을 해봐라.. 페이지가 바뀔 때마다... 핸들러가 살아 있다. 

불필요한 메모리를 사용하게 된다는 말이다.

앱이 터지기 싫으면 제때 제때 삭제 하자! 

 

위의 내용들을 정리해보면..

앱에 웹이 나오면 백 핸들러를 이용해 등록한다.

goBack()을 이용해 뒤로 간다.

뒤로 페이지에서 반복한다. 

그러면 시마이..

 

2.2 복붙을 위한 코드!  개꿀 ㅇㅈ?  어 ㅇㅈ?  위에 꺼 왜 읽음? 

import React, { useEffect, useState, useRef } from "react";
import {useFocusEffect} from '@react-navigation/native';
import {
  Platform,
  BackHandler,
  Dimensions,
  SafeAreaView,
} from "react-native";
import { StatusBar } from 'expo-status-bar';

import { WebView } from "react-native-webview";
import Constants from "expo-constants";
import NetInfo from "@react-native-community/netinfo";
const BACKGROUND_COLOR = "#FFFFFF";

export default function App(props) {
   
    const WEBVIEW = useRef()
    
    const [backButtonEnabled, setBackButtonEnabled] = useState(false)

    // Webview content loaded
    function webViewLoaded() {
      setLoading(false)
      setBackButtonEnabled(true);
    };
   
    // Webview navigation state change
    function onNavigationStateChange(navState) {
      setBackButtonEnabled(navState.canGoBack)
    
    };
   
    useEffect(() => {
      // Handle back event
      function backHandler() {
        if (backButtonEnabled) {
          WEBVIEW.current.goBack();
          return true;
        }
      };
      // Subscribe to back state vent
      BackHandler.addEventListener("hardwareBackPress", backHandler);
   
      // Unsubscribe
      return () => BackHandler.removeEventListener("hardwareBackPress", backHandler);
    }, [backButtonEnabled])

   
    return (
      <SafeAreaView
        style={{
          flex: 1,
          backgroundColor: BACKGROUND_COLOR,
        }}
      >
        <StatusBar style="auoto" />

          <WebView
            style ={{marginTop :30,}}
            onLoad={webViewLoaded}
            ref={WEBVIEW}
            // javaScriptEnabled={true}
            onNavigationStateChange={onNavigationStateChange}
            // onLoad ={(a)=>setWebViewStack(webViewStack+1)}
            onLoadStart={(e) => {
            }}
            onLoadEnd={(e) => {
            }}
            renderError={(e) => {
            }}
            source={{ uri: "너_의_사_이_트" }}
          />
        
       </SafeAreaView>
    );
  }
  

 

Comments