React native webview - this.webview doesn't exist - react-native

I am pretty new to react-native. Currently, I am developing an app with react native web-view.
My requirement is to open external links of the app in a chrome tab. To achieve that I used the following code.
<WebView
source={{uri: catalog_url}}
onNavigationStateChange={(event) => {
if (!event.url.includes(home_url)) {
this.WebView.stopLoading()
Linking.openURL(event.url);
}
}}
/>
But I found that the highlighted line is not working currently.
Any reference to this.WebView line gives an error saying
this.WebView doesn't exist.
I need an alternative to this.WebView.

If you want to reference of this webview. First, you must assign a reference like that.
<WebView
ref={webview => this.WebView = webview}
source={{uri: catalog_url}}
onNavigationStateChange={(event) => {
if (!event.url.includes(home_url)) {
this.WebView.stopLoading()
Linking.openURL(event.url);
}
}}
/>

So you have missed the ref props from the WebView component
Solution
<WebView
ref={(ref) => (this.WebView = ref)}
source={{ uri: catalog_url }}
onNavigationStateChange={(event) => {
if (!event.url.includes(home_url)) {
this.WebView.stopLoading();
Linking.openURL(event.url);
}
}}
/>
If you need more reference about how to use WebView in RN visit here

Related

React-Native webview - unhandled promise about:blank in IOS

The same website works absolute fine in android, however in iOS it seems to come up with this message:
Possible Unhandled Promise Rejection (id:11): Error: Unable to open URL about:blank
I also seem to get this when the site URI is linking to URLs from a different domain.
I have tried adding: originWhitelist={['*']}
Here is the Webview code:
<WebView
style={styles.flexContainer}
startInLoadingState
renderLoading={() =>
<View style={styles.container}>
<ActivityIndicator size="large" color="#ffffff" styles={styles.loader}/>
</View>
}
onMessage={event => {
parseWebData(event.nativeEvent.data);
}}
onShouldStartLoadWithRequest={event => {
if (!event.url.startsWith(base)) {
Linking.openURL(event.url)
return false
}
return true
}}
originWhitelist = {['*']}
source = {{ uri: base + uri }}
/>
1st try this one
<WebView
source={{ uri: base + uri }}
style={{ height: 400, width: 400 }}
useWebKit={true}
startInLoadingState={false}
javaScriptEnabled
domStorageEnabled
/>
onShouldStartLoadWithRequest={event => {
if (!event.url.startsWith(base)) {
Linking.openURL(event.url)
return false
}
return true
}}
This was the problem.
iOS treats any URL load with this, whereas Android only fires this on clicking.
See this post for the explanation of the issue:
onShouldStartLoadWithRequest automatically calling in iOS React Native on loading of any url in WebView, How to control it?

How to trigger another app from React Native Webview? UNKNOWN_URL_SCHEME error

From the React Native WebView to be able to open the related platform of Deep Link Scheme.
For example:
When the website I am viewing is trying to trigger another app.
<WebView
style={styles.container}
originWhitelist={['*']}
bounces={false}
allowFileAccess={true}
domStorageEnabled={true}
javaScriptEnabled={true}
geolocationEnabled={true}
allowFileAccessFromFileURLS={true}
allowUniversalAccessFromFileURLs={true}
onNavigationStateChange={onNavigationStateChange}
source={{
uri:
'http://onelink.to/6vdhky',
}}
/>
https://github.com/react-native-community/react-native-webview/issues/750
https://github.com/react-native-webview/react-native-webview/pull/1136
image ref one
image ref two
I tried Linking.sendIntent() and Editing shouldOverrideUrlLoading() function in RNCWebViewManager.java but didn’t make it work. I finally ended up with https://github.com/lucasferreira/react-native-send-intent#readme
Here’s my code like:
onShouldStartLoadWithRequest={(request) => {
const { url } = request;
if (
url.startsWith('intent://') &&
url.includes('scheme=kbzpay') &&
Platform.OS === 'android'
) {
SendIntentAndroid.openChromeIntent(url);
return false;
}
return false;
}}
VAT/BTW number (optional)
Plus3dhedset
VAT/BTW number must be in NL123456789B12 format.
https://domains.google.com/registrar?favorites=0e70b499-a0f1-4bc6-850a-793c6f8392c7

what does "this" mean in WebView component at props "ref" in react native webview

i try to injectJavaScript in react native web view like bellow work well
setTimeout(() => {
this.webref.injectJavaScript(someJSCODE);
}, 3000);
<WebView
ref={r => this.webref = r}
source={{uri: 'https://accounts.google.com/'}}
/>
but if i call r.injectJavaScript(someCode) it not working.
<WebView
ref={r => r.injectJavaScript(somecode)}
source={{uri: 'https://accounts.google.com/'}}
/>
Can you try the following ,
...
<WebView
source={{
uri: "https://************.org/privacy-policy/"
}}
ref={WEBVIEW_REF => (this.WebViewRef = WEBVIEW_REF)}
javaScriptEnabled={true}
injectedJavaScript={
"document.getElementsByClassName('site-content')[0].style.paddingTop='0px',document.getElementsByClassName('header')[0].style.display='none', document.getElementsByClassName('footer')[0].style.display='none',document.getElementsByClassName('subscribe-line')[0].style.display='none'"
}
onLoadProgress={e => this._onLoading(e.nativeEvent.progress)}
/>
...

How can I Refresh Web View in React Native?

I have a webview as tab A and a todolist flatlist on tab B. If the user adds an entry to the flatlist on tab B, i want the tab A webview to refresh.
I couldn't find any .refresh() or reload() methods on the webview control https://facebook.github.io/react-native/docs/webview.html
Any ideas how to accomplish this?
You can set a key to the webview
key={this.state.key}
and then you can reload it by updating the state
this.setState({ key: this.state.key + 1 });
Well I reload WebView by doing following:
render() {
let WebViewRef;
return (
<View style={Style1.container}>
<WebView
ref={WEBVIEW_REF => (WebViewRef = WEBVIEW_REF)}
source={{ uri: this.state.site }}
renderLoading={this.ActivityIndicatorLoadingView}
startInLoadingState={true}
/>
<Button title="Reload Me!" onpress={() => { WebViewRef && WebViewRef.reload(); }} />
</View>
)
}
In this code I Declare Reference Variable WebViewRef first then assign this to WebView as ref={WEBVIEW_REF => (WebViewRef = WEBVIEW_REF)} and then call this reference for reload() as ()=>{ WebViewRef && WebViewRef.reload();}
The react-native-community/react-native-webview component has a .reload() method on the ref.
const webViewRef = useRef();
// ...
return (
<WebView ref={(ref) => webViewRef.current = ref} ... />
)
// ...
You can then use the following to reload:
webViewRef.current.reload();
I ended up using a dummy query parameter to signal a refresh of the web view:
In Tab B, I dispatch a change which changes "latestItemId" in the global state.
In Tab A, I use mapStateToProps which maps to <WebView source={{uri:URL?latestItemId=${latestItemId}}} /> in the render method. This causes it to think it's a new url and reload it.
Reload was not working on my end.
If you want to refresh on focus change you can use the hook useFocusEffect of react navigation and in the unmount clean the URL used in the webview. Then in the initialize you need to set that again. Maybe using a a useState.
useFocusEffect(
useCallback(() => {
setUrl(url!);
return () => {
setUrl(undefined);
};
}, [url]),
);
In my case I have source={{html}} so refresh() won't work in that situation. However, in my case I am still able to inject javascript so I can set some properties specifically document.styles.body.color to match dark and light mode.
const fg = colorScheme === "light" ? "black" : "white";
const webViewRef = createRef<WebView>();
useEffect(() => {
webViewRef.current?.injectJavaScript(`
document.body.style.color='${fg}';
true
`);
}, [fg]);
...
<WebView
ref={webViewRef}
originWhitelist={["*"]}
style={{
height: 200,
backgroundColor: "transparent",
}}
onMessage={() => {}}
javaScriptEnabled={true}
injectedJavaScript={`
document.body.style.color='${fg}';
true;`}
source={{ html }}
/>

How to get the html source of WebView object in react native

I'm trying to access the HTML source code of a 3rd party web page to read a specific DOM element value of a page which is loaded in WebView component in react-native.
<WebView
source={{uri: 'https://www.amazon.com'}}
/>
and Suppose there's a DOM element like this:
<span class="price bold some-class-name">$459.00</span>
I also tried this component but could not do that:
https://github.com/alinz/react-native-webview-bridge
Is there any way to get the current HTML source code of page inside a WebView and Read specific DOM element value?
Looks like this functionality was added in React Native v0.37. Adding an onMessage parameter will inject a postMessage variable into your WebView. You can then just inject JavaScript as normal, select your element and postMessage it back.
render (
const jsCode = "window.postMessage(document.getElementsByClassName("price bold some-class-name"))"
return (
<View style={styles.container}>
<WebView
source={{uri: "http://..."}}
onMessage={this._onMessage}
injectedJavaScript={jsCode}
/>
</View>
);
)
The answer by Brian F is great and helped me a lot. There is just one thing missing. You need to append ReactNativeWebView to the postMessage function.
So it would look like
render (
const jsCode = "window.ReactNativeWebView.postMessage(document.getElementsByClassName("price bold some-class-name"))"
return (
<View style={styles.container}>
<WebView
source={{uri: "http://..."}}
onMessage={this._onMessage}
injectedJavaScript={jsCode}
/>
</View>
);
)
In my experience, It will work well, because I've tried to get product information from Amazon and Taobao, Rakuten.
_onMessage = (message) => {
// you can put processing code here.
}
render (
const jsCode = "window.ReactNativeWebView.postMessage(document.getElementsByClassName("class name"))"
// or you can use `document.querySelector("element query")` instead of `document.getElementsByClassName("class name")`
return (
<View style={styles.container}>
<WebView
source={{uri: "url here"}}
onMessage={this._onMessage}
injectedJavaScript={jsCode}
/>
</View>
);
)
For those who are still not getting then try this for the latest react-native
window.ReactNativeWebView.postMessage(document.getElementById('id_here').innerHTML);
const INJECT_JS = `window.ReactNativeWebView.postMessage(document.getElementById('id_here').innerHTML);
alert("Hel0....")
`
return (
<View style={styles.container}>
<WebView
source={{uri: "http://..."}}
onMessage={event => {
console.log(event.nativeEvent.data);
}}
injectedJavaScript={INJECT_JS }
/>
</View>
);
<WebView
source={{html: "<span class="price bold some-class-name">$459.00</span>"
/>
or you can right your template into a constant, then do this:
const HTMLTemplate = `<span class="price bold some-class-name">$459.00</span>`;
<WebView
source={{html: HTMLTemplate}}
/>