Get HTML content of webpage with webview - react-native

I want to get html code with webview in react native my current code only can call alert function after its injected. i want to get a specific div html content.
const jsCode = "window.postMessage(alert(document.getElementById('result')))"
<WebView
style={{width:Dimensions.get('window').width,height:Dimensions.get('window').height}}
javaScriptEnabled ={true}
injectedJavaScript={jsCode}
source={{uri: this.state.uri}}
/>

window.postMessage causes the WebView.onMessage-handler to get called with the data.
So this should work:
const jsCode = "window.postMessage(document.getElementById('gb-main').innerHTML)"
<WebView
javaScriptEnabled={true}
injectedJavaScript={jsCode}
source={{uri: 'http://www.google.com/'}}
onMessage={event => console.log('Received: ', event.nativeEvent.data)}
/>

Related

How do I get a POST response using React Native WebView?

I am trying to extract the POST response from the WebView in React Native but onMessage doesn't seem to solve this. The code below works to navigate a website using the WebView but it does not console.log anything. Is there anything I'm missing or misreading in the documentation for WebView?
import { WebView } from "react-native-webview";
return (
<WebView
source={{
uri: `https://www.example.com/`
}}
onMessage={(event)=>console.log(event)}
/>
);
The onMessage function is used for Web and communication.
You can use window.ReactNativeWebView.postMessage
Example
const runFirst = `window.ReactNativeWebView.postMessage("this is message from web");`;
<WebView
source={{
uri:
'https://github.com/react-native-community/react-native-webview',
}}
injectedJavaScript={runFirst}
onMessage={(event)=> console.log( "On Message", event.nativeEvent.data )}
/>

React Native WebView not working IOS simulator

Does the WebView work in IOS simulator?
The code below does not return an error, but also doesn't display anything.
import React, { Component } from 'react';
import { WebView } from 'react-native';
class MyTest extends Component {
render() {
return (
<WebView
source={{uri: 'https://github.com/facebook/react-native'}}
style={{marginTop: 20}}
/>
);
}
}
export default MyTest;
Thanks
WebView work well in my simulator. My code:
<WebView
useWebKit={true}
style={{flex:1}}
source={{uri:url}}
startInLoadingState={true}
renderLoading={()=>(<ActivityIndicator size='large' color={COLOR_STANDARD}
style={{marginTop:100}} />)}>
</WebView>
I want to contribute here for those getting white screen on ios. First the webview is inside scrollview because I have other content. I know it is adviced for webview not to be inside any component. I was battling this for weeks until I came upon James Liu's. I was running it on expo client (ios) and was getting white screen. Here is my code before I saw his answer.
contentContainerStyle={{
flexGrow: 1,
}}>
<WebView
ref={ref => (this.webview = ref)}
source={{uri: currentSite}}
style={{ height:550}}
scrollEnabled={true}
startInLoadingState={true}
onNavigationStateChange={this._onNavigationStateChange.bind(this)}
javaScriptEnabled = {true}
domStorageEnabled = {true}
startInLoadingState={false}
onLoad={() => this.hideSpinner()}
injectedJavaScript={jsCode}
onMessage={event => {
//Html page
const wishData = event.nativeEvent.data;
this._getProductName(wishData);
this._getProductPrice(wishData);
}}
/>
</ScrollView>
All I needed to add is useWebKit={true} and from the documentation it says:
useWebKit->If true, use WKWebView instead of UIWebView. And this props is ios specific. Furthermore, I googled and found that WKWebView is more recent than UIWebView ( I don't know more about this).
For me, the solution was to wrap my component that returned my WebView in a View with a set height OUTSIDE the file with the component that returns my WebView.
The wrapper View with the height should be in the file that component with the WebView was imported into.
It took several takes and prayer but I finally found it out muahahaha!
The real problem is in the property startInLoadingState, you have to set this to true:
<WebView
startInLoadingState={true} />

How to detect tapped word in WebView?

I have a simple WebView and would like to know which word in it was tapped. For example if a user taps on any of the words in the article on the picture, such as "balloon", I would like to capture that.
Here is the code and the render.
export default class App extends React.Component {
render() {
return (
<View style={{top:100, height: 500, backgroundColor:'red' }}>
<WebView
source={{uri: 'https://www.reuters.com/article/us-art-banksy/we-just-got-banksy-ed-balloon-girl-painting-self-destructs-at-sale-idUSKCN1MG0B4?feedType=RSS&feedName=artsNews'}}
style={{height:"200", marginTop: 20}}
/>
</View>
);
}
}
UPDATE:
This is how I got WebView to communicate back the JS events based on #pritesh answer.
<WebView
source={{uri: 'https://www.reuters.com/article/us-art-banksy/we-just-got-banksy-ed-balloon-girl-painting-self-destructs-at-sale-idUSKCN1MG0B4?feedType=RSS&feedName=artsNews'}}
style={{height:"200", marginTop: 20}}
javaScriptEnabled={true}
injectedJavaScript={`document.body.addEventListener('click',
function(e){
window.postMessage("Message from WebView","*");
console.log(e);
})`}
onMessage={e => console.log("message", e)}
/>
On top of my head one approach you can try is by using the injectJavascript or injectedJavascript props of WebView.So you can register some kind of listener on the body and the use it to detect what is being pressed, like:
<WebView
ref={c => this._webview = c}
javaScriptEnabled={true}
injectedJavaScript={`document.body.addEventListener('click', function(e){
console.log(e)
})`}
/>
But you check to research how to pass the callback from Webview to React.

React Native load dynamic content onto webview

Currently I am loading a html file from my android assets folder into webview.
dashboard.html file contains some scripts.
if its static it works fine.
<WebView
ref={(component) => (this.webview = component)}
style={{ height: height * 1.3 }}
javaScriptEnabled={true}
domStorageEnabled={true}
source={{uri:'file:///android_asset/graph/pages/dashboard.html'}}
startInLoadingState={true}
javaScriptEnabledAndroid={true}
mixedContentMode={'compatibility'}
/>
But I need to dynamically update a variable in my script.
How can I access scripts placed in assets folder from react-native component.
You can use forceUpdate();
e.g.
<webView source={{html: this.state.html}}></webView>
onTestBtnClicked() {
const html = '<div>test1</div>';
this.setState({ html });
this.forceUpdate();
}
You can't access and update a script file but maybe you can run your script or extra code once the WebView is loaded using the injectedJavaScript prop
Example:
const injectedJs = `
alert("My custom code will go here!");
`;
return (
<WebView
ref={(component) => (this.webview = component)}
style={{ height: height * 1.3 }}
javaScriptEnabled={true}
domStorageEnabled={true}
source={{uri:'file:///android_asset/graph/pages/dashboard.html'}}
startInLoadingState={true}
javaScriptEnabledAndroid={true}
mixedContentMode={'compatibility'}
injectedJavaScript={injectedJs}
javaScriptEnabledAndroid={true}
/>
);

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}}
/>