Yes
Yes
Environment:
OS: macOS High Sierra 10.13.3
Node: 8.9.3
Yarn: 1.1.0
npm: 5.5.1
Watchman: 4.9.0
Xcode: Xcode 9.2 Build version 9C40b
Android Studio: 1.4 AI-141.2343393
Packages: (wanted => installed)
react: 16.2.0 => 16.2.0
react-native: 0.53.3 => 0.53.3
I would expect to see a console log "On message" in my android using 'adb logcat' when triggering the window.postmessage from within the webview.
Nothing displays in the log when triggering window.postmessage. Communication the other way from the app into the webview using injected javascript works ok.
App code to be pasted into App.js after running "react-native init":
import React, {Component} from "react";
import {AppRegistry, Text, View, TouchableHighlight, WebView} from "react-native";
export default class WevViewApp extends Component {
constructor( props ) {
super( props );
this.webView = null;
}
onMessage( event ) {
console.log( "On Message", event.nativeEvent.data );
}
sendPostMessage() {
console.log( "Sending post message" );
this.webView.postMessage( "Post message from react native" );
}
render() {
return (
<View style={{flex: 1}}>
<TouchableHighlight style={{padding: 10, backgroundColor: 'blue', marginTop: 20}} onPress={() => this.sendPostMessage()}>
<Text style={{color: 'white'}}>Send post message from react native</Text>
</TouchableHighlight>
<WebView
style={{flex: 1}}
source={{uri: 'https://popping-heat-6062.firebaseapp.com'}}
ref={( webView ) => this.webView = webView}
onMessage={this.onMessage}
/>
</View>
);
}
}
AppRegistry.registerComponent( 'WevViewApp', () => WevViewApp );
The code for the webview html can be found at: https://popping-heat-6062.firebaseapp.com
This code was based on a stackoverflow question: https://stackoverflow.com/questions/41160221/react-native-webview-postmessage-does-not-work
This behavior is already covered in the tests, which are currently passing. See WebViewExample.js.
Can you dig a little further and figure out why your particular use case is failing?
Thanks for pointing me to the tests. I'll review the tests, examine it a bit more and see if I can narrow it down more.
I've investigated and found a workaround for my issue. Foundings below:
First off: In the webpage I linked to from the stackoverflow post there was a bug, it used document.postmessage instead of window.postmessage.
In my tests I tried to trigger the postmessage command onload. This failed. Once I added a timeout before posting it works ok. You can add the following to your test to illustrate the issue:
document.addEventListener('DOMContentLoaded', function () {
window.postMessage('Without timeout'); // Doesnt work
setTimeout(() => window.postMessage('With timeout'), 5000); // Works
}, false)
Just leaving a note, I was able to get this to work without needing DOMContentLoaded or a long timeout. This worked:setTimeout(() => window.postMessage('With timeout'), 0)
Hi all,
I am working on react Native webview, I try to post some message to onMessage() function in Webview props. It's work very well in some of the android devices and some of it's not working. I am not able to identify what the issue can you please help me? please check the below code @staffannase @hramos @ratbeard @mojodna @jsierles
// calling from HTML cide
setTimeout(() => postMessage('Calling from HTML'), 1000);
// WebView components
<WebView
source={{ html: concatHTML, baseUrl: 'web/' }}
javaScriptEnabled={true}
javaScriptEnabled={true}
domStorageEnabled={true}
scalesPageToFit={true}
scrollEnabled={false}
automaticallyAdjustContentInsets={true}
style={{ height: 390, width: 390, justifyContent: 'center' }}
onMessage={m => console.warn(m.nativeEvent.data)} />
I am facing the same issue on iOS and rn 0.57.2 ..onMessage does not logs any message./
Note same is working on android
@viv3kk can you please share your code here? , so we can look at into that
_onMessage = event => {
this.props.getTitle(event.nativeEvent.data.message) // event.nativeEvent: null
}
render() {
return (
{...this.props}
useWebKit={true}
onShouldStartLoadWithRequest={this.startLoadWithRequest}
injectedJavaScript={this.injectedJS}
onMessage={this._onMessage}
decelerationRate="normal"
/>
)
}
@ap050492 me too, the same issue on IOS and rn 0.57.2 , onMessage response the event.nativeEvent
null , so i cant take anything from onMessage
after try all the way, i found using "postMessage" directly on RN0.56,works well so simple on both iOS & Android!
just one important thing is make sure the “HTML side code” has nothing errors or warnings in browser !
and the only problem is there is a yellow box "Error: Unable to open URL: about:blank" , i hadn't solved it yet !
html side:
// send message to RN

// get message from RN

RN side:

// get message from webview

// send message to webview

Hi, I am using Highcharts to plot charts in a webview. On Clicking on certain points on the chart i need to get data from each clicked point in the RN code. I run the following code in the click event of highcharts
click: function (event) {
console.log('[On Click]', window);
postMessage(JSON.stringify({
name: this.name,
x: event.point.category,
y: event.point.y
}));
}
On the RN side,
onMessage(event) {
console.log('[RN][On Message] start')
debugger;
console.log("On Message", event.nativeEvent.data);
}
<WebView
ref={webview => { this.webview = webview; }}
onLayout={this.reRenderWebView}
style={styles.full}
source={{ html: concatHTML, baseUrl: 'web/' }}
javaScriptEnabled={true}
domStorageEnabled={true}
scalesPageToFit={true}
scrollEnabled={false}
automaticallyAdjustContentInsets={true}
onMessage={this.onMessage.bind(this)}
{...this.props}
/>
Firstly, on debugging WebView, the following code returns error
postMessage(JSON.stringify({
name: this.name,
x: event.point.category,
y: event.point.y
}));
returns error
Uncaught TypeError: Failed to execute 'postMessage' on 'Window': 2 arguments required, but only 1 present.
to fix this i had to do the following
postMessage(JSON.stringify({
name: this.name,
x: event.point.category,
y: event.point.y
}), '*');
By doing this I dont get the error anymore, but onMessage={this.onMessage.bind(this)} never gets fired. I dont see an error on the webview nor on the RN side. Not sure what am I doing wrong.
Please help
@ws7one
DO NOT use local html resource, there are lots of problems I tried, especially on android release apk!
put the local html file on to the server end!
I found some solution for this problem. Just, i inject following script into webview:
const script = `
function postMessage(message) {
var hash = window.location.hash;
window.location.hash='message=' + message;
window.location.hash=hash;
}
//Now just call following function
postMessage('Any message');
`;
After i create component:
export default class SomeWebComponent extends Component {
handleNavigation = (event) => {
const url = event.url;
const sections = url.split('#');
if(sections.length > 1 && sections[1].indexOf('message=') != -1) {
const message = sections[1[.replace('message=', '');
//Do any action with message
return;
}
//Other navigation actions
}
render() {
return (
<WebView
source={anySource}
injectedJavaScript={script}
javaScriptEnabled = {true}
onNavigationStateChange = {this.handleNavigation}
/>
);
}
}
I hope what it may help you))
@Raserad great idea .... but it didnt work here with expo 32. What I did to solve the issue, inspired in your idea, was to use window.location and did the same thing. But, in my case, I couldnt use postMessage, since it wasnt working on expo. I had to implement a custom onShouldStartLoadWithRequest in order to not go to my "message urls".
Most helpful comment
I've investigated and found a workaround for my issue. Foundings below:
First off: In the webpage I linked to from the stackoverflow post there was a bug, it used document.postmessage instead of window.postmessage.
In my tests I tried to trigger the postmessage command onload. This failed. Once I added a timeout before posting it works ok. You can add the following to your test to illustrate the issue:
document.addEventListener('DOMContentLoaded', function () {
window.postMessage('Without timeout'); // Doesnt work
setTimeout(() => window.postMessage('With timeout'), 5000); // Works
}, false)