The complete guide to React Native WebView 정보
The complete guide to React Native WebView관련링크
본문
간단히 말해서 WebView 는 React Native 앱에서 웹 페이지를 로드하는 데 사용되는 구성 요소입니다. 이전에는 React Native 에서 즉시 사용할 수 있었지만 이제 React Native 코어에서 제거되어 React Native Community 라이브러리의 구성 요소로 추가됩니다. 자세한 내용은 The Slimmening proposal을 참조하십시오. 이제 react-native-webview 라이브러리를 설치해야 합니다.
Platforms supported
저는 React Native 개발자이기도 하므로 앱에서 사용할 라이브러리에 대해 플랫폼간 지원이 얼마나 중요한지 이해합니다. 앱에서 라이브러리를 사용해야 할 때마다 가장 먼저 묻는 것은 크로스 플랫폼인지 여부입니다. react-native-webview 에 대해 걱정할 필요가 없습니다. iOS 및 Android 플랫폼을 모두 지원합니다.
참고: React Native WebView 에 대한 Expo 지원은 Expo SDK v33.0.0로 시작되었습니다.
Getting started
먼저 아래 명령을 실행하여 라이브러리를 설치해야합니다.
// with yarn
$ yarn add react-native-webview
// with npm
$ npm install --save react-native-webview
그런 다음 종속성을 연결하십시오. react-native 0.60 부터 자동 연결은 연결 프로세스를 처리하지만 pod install
를 실행하는 것을 잊지 마십시오.
React 네이티브 Objective-C, Swift, Java 또는 Kotlin 코드를 포함하는 네이티브 모듈은 컴파일러가 앱에 포함할 수 있도록 link
되어야합니다.
연결하려면 아래 명령을 실행하십시오.
$ react-native link react-native-webview
For iOS:
ios/
디렉토리에서 CocoaPods 를 사용하는 경우 다음을 실행하십시오.
$ pod install
For Android:
react-native-webview 버전≥ 6.X.X 를 사용하는 경우 android/gradle.properties
를 편집하고 아래 두 줄을 추가하여 프로젝트에서 AndroidX 를 사용하도록 설정하십시오.
android.useAndroidX=true
android.enableJetifier=true
참고 : React Native WebView 를 제거해야하는 경우
react-native unlink react-native-webview
를 실행하여 링크를 해제하십시오.
성공적으로 설치했으면 합니다. 어딘가에 갇힌 경우 공식 설치 안내서를 참조하십시오.
이제 간단한 것부터 고급까지 WebView 의 유용한 예와 그 이후의 사용법을 보여 드리겠습니다.
Basic quickstart
WebView 의 기본 속성을 검토하여 시작하겠습니다.
import React, { Component } from 'react';
import { WebView } from 'react-native-webview';
class MyWeb extends Component {
render() {
return (
<WebView
source={{ uri: 'https://logrocket.com/' }}
style={{ marginTop: 20 }}
/>
);
}
}
먼저 source
속성은 URL 또는 HTML 에서 컨텐츠를 가져 오는 데 사용됩니다. URL 로 웹 페이지를 로드하려면 아래와 같이 uri
속성을 가진 객체를 전달해야 합니다.
<WebView
source={{ uri: 'https://logrocket.com/' }}
/>
Loading inline HTML
위의 URL 로 웹 페이지를 로드하는 방법을 보았습니다. 그러나 HTML 을 직접 로드하려는 경우 아래와 같이 WebView 의 source
속성에서 html
속성을 사용할 수 있습니다.
<WebView
originWhitelist={['*']}
source={{ html: '<h1>Hello world</h1>' }}
/>
참고 : HTML 소스를 설정하려면 originWhiteList 속성을 ['*']로 설정해야 합니다.
What is the originWhitelist
property anyway?
간단히 말해 originWhitelist
속성은 사용자가 WebView 에서 탐색 할 수 있는 위치를 제어합니다. 문자열 배열이 필요하며 기본 whitelisted
원점은 http://
및 https://
입니다.
예를 들어, 사용자가 https://
또는 git://
로 시작하는 URI 만 탐색할 수 있도록 하려면 다음과 같이 구현하십시오.
<WebView
source={{ uri: 'https://logrocket.com/' }}
originWhitelist={['https://*', 'git://*']}
/>
다른 예를 살펴 보겠습니다.
Loading local HTML files
때로는 WebView 에 로드하려는 HTML 파일이 앱과 함께 로컬로 있습니다.
iOS 에서는 아래 예제와 같이 다른 자산과 마찬가지로 HTML 파일을 가져 오기만 하면 됩니다.
import React, { Component } from 'react';
import { WebView } from 'react-native-webview';
const myHtmlFile = require("./my-asset-folder/local-site.html");
class MyWeb extends Component {
render() {
return (
<WebView source={myHtmlFile} />
);
}
}
매우 간단합니다. 정확히 예상했던 것입니다.
그러나 Android 에서는 HTML 파일을 Android 자산 디렉토리에 넣어야합니다. 예를 들어, 안드로이드 앱에 logrocket.html
이라는 파일을 로드하려면 안드로이드 자산 디렉토리인 yourProject/android/src/main/assets/
로 이동해야 합니다.
그런 다음 아래 예제와 같이 HTML 파일을 로드할 수 있습니다.
import React, { Component } from 'react';
import { WebView } from 'react-native-webview';
class MyWeb extends Component {
render() {
return (
<WebView source={{ uri: "file:///android_asset/logrocket.html" }} />
);
}
}
Controlling navigation state changes by user
onNavigationStateChange
는 WebView
로딩이 시작되거나 종료될 때 호출되는 함수입니다.
탐색 상태 변경을 제어하고 WebView 에서 탐색하는 것과 다른 작업을 수행해야 하는 경우 이를 수행하는 완벽한 방법입니다. 예를 들면 다음과 같습니다.
import React, { Component } from 'react';
import { WebView } from 'react-native-webview';
class MyWeb extends Component {
webview = null;
render() {
return (
<WebView
ref={ref => (this.webview = ref)}
source={{ uri: 'https://logrocket.com/' }}
onNavigationStateChange={this.handleWebViewNavigationStateChange}
/>
);
}
handleWebViewNavigationStateChange = newNavState => {
// newNavState looks something like this:
// {
// url?: string;
// title?: string;
// loading?: boolean;
// canGoBack?: boolean;
// canGoForward?: boolean;
// }
const { url } = newNavState;
if (!url) return;
// handle certain doctypes
if (url.includes('.pdf')) {
this.webview.stopLoading();
// open a modal with the PDF viewer
}
// one way to handle a successful form submit is via query strings
if (url.includes('?message=success')) {
this.webview.stopLoading();
// maybe close this view?
}
// one way to handle errors is via query string
if (url.includes('?errors=true')) {
this.webview.stopLoading();
}
// redirect somewhere else
if (url.includes('google.com')) {
const newURL = 'https://logrocket.com/';
const redirectTo = 'window.location = "' + newURL + '"';
this.webview.injectJavaScript(redirectTo);
}
};
}
이 메소드는 해시 URL 변경시 호출되지 않습니다 (예: [https://logrocket.com/users#list](https://logrocket.com/users#list)
에서 [https:/ /logrocket.com/users#help](https://logrocket.com/users#help)
). 그러나 버전 8.0.0 부터 iOS 에서 onNavigationStateChange
를 사용하면 URL 이 #번 변경될 때 트리거됩니다.
How to add support for file uploads
WebView 에서 파일 업로드를 허용하려면 아래 권한을 추가해야 합니다. 아래에서 작업과 플랫폼으로 구분하여 필요한 것을 정확하게 선택할 수 있습니다.
For iOS:
iOS 를 사용한다면 ios/[project]/Info.plist
파일에 권한을 지정하기만 하면 됩니다.
사진 캡처의 경우:
<key>NSCameraUsageDescription</key>
<string>Take pictures for certain activities</string>
갤러리 선택의 경우:
<key>NSPhotoLibraryUsageDescription</key>
<string>Select pictures for certain activities</string>
비디오 녹화의 경우:
<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for recording videos</string>
For Android:
AndroidManifest.xml
에 권한을 추가하십시오. `/Android/app/src/main/AndroidManifest.XML 에 있습니다.
Android 개발을 시작할 때 프로젝트에서 해당 파일을 찾는 데 실제로 문제가 발생했기 때문에 해당 파일 위치를 추가했습니다.
<manifest ...>
......
<!-- this is required only for Android 4.1-5.1 (api 16-22) -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
......
</manifest>
<input type="file"/>
을 사용한 파일 업로드는 Android 4.4 KitKat 에서 지원되지 않습니다 (자세한 내용은 여기 참조) - 파일 업로드가 지원되는지 확인하려면 isFileUploadSupported()
를 사용하여 파일 업로드를 확인할 수 있습니다. 아래 예를 참조하십시오.
WebView.isFileUploadSupported().then(res => {
if (res === true) {
// file upload is supported
} else {
// file upload is not supported
}
});
Controlling multiple file uploads
어쨌든 단일 및 다중 파일 업로드를 제어하려면 아래 예제와 같이 input
요소에 다중 속성을 추가하면됩니다.
// multiple file selection
<input type="file" multiple />
// single file selection
<input type="file" />
Adding support for file downloads
예, 사용자가 WebView 에서 파일을 다운로드할 수 있게 하려면 해당 권한을 추가해야 합니다.
For iOS:
iOS 의 경우 ios/[project]/Info.plist
파일에 권한을 지정하기만 하면 됩니다.
갤러리에 저장:
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Save pictures for certain activities.</string>
For Android:
/android/app/src/main/AndroidManifest.xml
에 있는 AndroidManifest.xml
에 권한을 추가하십시오:
<manifest ...>
......
<!-- this is required to save files on Android -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
......
</manifest>
How to inject JavaScript in WebView
때로는 WebView 로 JavaScript 를 실행하려는 상황에 처할 수도 있습니다. 이 경우 WebView 는 다음과 같은 세 가지 방법을 제공합니다.
injectedJavaScript
propinjectJavaScript
methodpostMessage
method 와onMessage
prop
The injectedJavaScript
prop
이 메소드는 웹 페이지가 처음으로 로드된 직후 제공된 스크립트를 실행합니다. 페이지가 다시 로드되거나 사용자가 이동하더라도 한 번만 실행됩니다. 예를 들면 다음과 같습니다.
import React, { Component } from 'react';
import { View } from 'react-native';
import { WebView } from 'react-native-webview';
export default class App extends Component {
render() {
const myScript = `
document.body.style.backgroundColor = 'red';
setTimeout(function() { window.alert('hi') }, 2000);
true; // note: this is required, or you'll sometimes get silent failures
`;
return (
<View style={{ flex: 1 }}>
<WebView
source={{
uri:
'https://github.com/react-native-community/react-native-webview',
}}
injectedJavaScript={runFirst}
/>
</View>
);
}
}
참고: 이유는 모르겠지만 공식 문서에 따르면 스크립트 끝에
true;
가 필요합니다. 사용하지 않으면 때로는 자동 실패가 발생하므로 포함하는 것이 좋습니다.
따라서 위 스크립트에서 배경색을 빨간색으로 설정하고 2 초 후에 hi
를 경고합니다. 아래 이미지에서 볼 수 있습니다. myScript
는 페이지가 로드되면 실행됩니다.
What’s going on internally?
iOS 에서 injectedJavaScript
는 WebView 에서 evaluateJavaScript:completionHandler:
라는 메소드를 실행합니다. 안드로이드에서 injectedJavaScript
는 안드로이드 웹뷰에서 evaluateJavascriptWithFallback
이라는 메소드를 실행합니다.
앞서 언급했듯이 injectedJavaScript
prop 은 컨텐츠 로드후 실행됩니다. 그러나 컨텐츠를 로드하기 전에 JavaScript 코드를 실행해야 하는 경우 어떻게 해야 합니까?
이를 위해 페이지가 처음 로드되기 전에 JavaScript 코드를 실행하는 injectedJavaScriptBeforeContentLoaded
라는 또 다른 소품이 있습니다. 페이지가 다시 로드되거나 사용자가 이동하더라도 한번만 실행됩니다. 코드를 실행하기 전에 창, localStorage
또는 문서에 무엇이든 삽입하려는 경우 이 소품을 사용할 수 있습니다.
import React, { Component } from 'react';
import { View } from 'react-native';
import { WebView } from 'react-native-webview';
export default class App extends Component {
render() {
const runFirst = `
window.isNativeApp = true;
true; // note: this is required, or you'll sometimes get silent failures
`;
return (
<View style={{ flex: 1 }}>
<WebView
source={{ uri: 'https://logrocket.com/' }}
injectedJavaScriptBeforeContentLoaded={runFirst}
/>
</View>
);
}
}
The injectJavaScript
method
injectedJavaScript
prop 의 단점은 한 번만 실행된다는 것입니다. 그렇기 때문에 WebView 참조에 injectJavaScript
라는 메소드를 노출시키는 이유도 있습니다. (이름에 약간의 차이가 있습니다!)
다음은 injectJavaScript
소품을 사용하는 방법입니다.
import React, { Component } from 'react';
import { View } from 'react-native';
import { WebView } from 'react-native-webview';
export default class App extends Component {
render() {
const run = `
document.body.style.backgroundColor = 'blue';
true;
`;
setTimeout(() => {
this.webref.injectJavaScript(run);
}, 3000);
return (
<View style={{ flex: 1 }}>
<WebView
ref={r => (this.webref = r)}
source={{ uri: 'https://logrocket.com/' }}
/>
</View>
);
}
}
3 초 후에 코드가 실행되고 배경이 파란색이됩니다.
What’s going on internally?
iOS 에서 injectJavaScript
는 WebView 의 evaluateJS:andThen:
을 호출합니다. Android 에서 injectJavaScript
는 Android WebView 의 evaluateJavascriptWithFallback
메소드를 호출합니다.
The window.ReactNativeWebView.postMessage
method and onMessage
prop
이전 접근법은 prop 을 사용하여 JavaScript 코드를 주입하는 데 실제로 도움이 됩니다. 그러나 웹 페이지가 React Native 코드로 무언가를 보내거나 통신하려면 어떻게해야합니까? 여기서window.ReactNativeWebView.postMessage
및 onMessage
prop 을 사용할 수 있습니다.
웹 페이지에 onMessage
또는 window.ReactNativeWebView.postMessage
메소드를 삽입하지 않도록 설정해야합니다.
import React, { Component } from 'react';
import { View } from 'react-native';
import { WebView } from 'react-native-webview';
export default class App extends Component {
render() {
const html = `
<html>
<head></head>
<body>
<script>
setTimeout(function () {
window.ReactNativeWebView.postMessage("Hello!")
}, 2000)
</script>
</body>
</html>
`;
return (
<View style={{ flex: 1 }}>
<WebView
source={{ html }}
onMessage={event => {
alert(event.nativeEvent.data);
}}
/>
</View>
);
}
}
코드의 결과는 Hello!
이며 아래 이미지와 같이 경고합니다.
Conclusion
이 기사 전체를 읽으면 React Native WebView 에서 사용할 것보다 더 많은 것을 알고 있다고 말할 수 있습니다. 항상 더 많이 아는 것이 좋습니다.
Plug: LogRocket, a DVR for Web apps
LogRocket은 마치 자신의 브라우저에서 발생한 것처럼 문제를 재생할 수 있는 프런트엔드 응용 프로그램 모니터링 솔루션입니다. LogRocket 을 사용하면 오류가 발생하는 이유를 추측하거나 사용자에게 스크린 샷 및 로그 덤프를 요청하는 대신 세션을 재생하여 무엇이 잘못되었는지 신속하게 이해할 수 있습니다. 프레임 워크에 관계없이 모든 앱에서 완벽하게 작동하며 Redux, Vuex 및 @ngrx/store 의 추가 컨텍스트를 기록하는 플러그인이 있습니다.
Redux 작업 및 상태 로깅 외에도 LogRocket 은 콘솔 로그, JavaScript 오류, 스택 추적, 헤더 + 본문이 있는 네트워크 요청/응답, 브라우저 메타 데이터 및 사용자 지정 로그를 기록합니다. 또한 DOM 을 계측하여 페이지에 HTML 및 CSS 를 기록하여 가장 복잡한 단일 페이지 앱의 완벽한 픽셀 비디오를 재생성합니다.
0
댓글 0개