How to get the html source of WebView object in react native - 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}}
/>

Related

I need to integrate CKeditor in react-native app

I need to integrate ckeditor or any editor alike inside react native,I found documentation for reactjs but not getting exact way to how to use inside RN app.
try this
https://github.com/vitalyliber/react-native-ckeditor
React Native CKEditor component with no native code for React Native apps built using WebView
here is the complete code.
import CKEditor from 'react-native-ckeditor'
const App = () => {
const [description, setdescription] = useState(`<p>The <code class=" language-php">firstOrNew</code> method, like <code class=" language-php">firstOrCreate</code> will attempt to locate a record in the database matching the given attributes. However, if a model is not found, a new model instance will be returned. Note that the model returned by <code class=" language-php">firstOrNew</code> has not yet been persisted to the database. You will need to call <code class=" language-php">save</code> manually to persist it:</p>`);
const setFieldValue = (value) => {
console.log(value);
}
return (
<>
<StatusBar barStyle="dark-content" />
<SafeAreaView>
<ScrollView
contentInsetAdjustmentBehavior="automatic"
style={styles.scrollView}>
<View style={styles.body}>
<View style={styles.sectionContainer}>
<CKEditor
content={description}
onChange={value => {
setFieldValue(value);
}}
style={{flex:1}}
/>
</View>
</View>
</ScrollView>
</SafeAreaView>
</>
);
};

React native List footer component not rendering(funtion component)

I am trying to achieve pagination for infinite scrolling in react native. When loading, I want to render the loading spinner at the bottom of the Flat list component. (Note: I'm using Expo for this app)
const renderFooter = () => {
if (!category.loading) return null;
return (
<View style={spinnerStyles.container}>
<ActivityIndicator animating size="large" color="#0000ff" />
</View>
);
};
return (
<View style={styles.container}>
<FlatList
columnWrapperStyle={{ justifyContent: "space-between" }}
numColumns={2}
data={category.data}
renderItem={categoryItem}
keyExtractor={(item) => item._id + item.sub_category}
onEndReachedThreshold={0}
listFooterComponent={renderFooter}
onEndReached={() => loadMore()}
/>
</View>
);
The loading spinner not correctly working with the flat list footer.
Has anyone run into this issue before, or does anyone have a solution?
Sorry, it's my simple syntax error. It's actually ListFooterComponent not listFooterComponent. Now it's working fine, Thank you.
Instead of calling the refrence, call the function. It should look something like this.
ListFooterComponent={renderFooter()}

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.

Get HTML content of webpage with webview

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

React Native: How to use Webview?

I've been testing out the WebView component, but I can't seem to get it to render things.
Sample here: https://snack.expo.io/r1oje4C3-
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.paragraph}>
Change code in the editor and watch it change on your phone!
Save to get a shareable url. You get a new url each time you save.
</Text>
<WebView source={{html: '<p>Here I am</p>'}} />
<WebView source={{ uri: 'http://www.google.com'}} />
</View>
);
}
}
When running the above example in Expo, neither of the two WebView components seem to render. What am I doing wrong?
It seems that you need to provide a width style parameter, like so :
<WebView
source={{uri: 'https://github.com/facebook/react-native'}}
style={{width: 300}}
/>
Note that you might have to provide a height style parameter as well. You can also add flex: 1 to the style.
add style prop with flex: 1 on WebView
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.paragraph}>
Change code in the editor and watch it change on your phone!
Save to get a shareable url. You get a new url each time you save.
</Text>
<WebView style={{flex: 1}} source={{html: '<p>Here I am</p>'}} />
<WebView style={{flex: 1}} source={{ uri: 'http://www.google.com'}} />
</View>
);
}
}