Skip to content

Instantly share code, notes, and snippets.

@blankg
Last active July 12, 2022 06:53
Show Gist options
  • Save blankg/d5537a458b55b9d15cb4fd78258ad840 to your computer and use it in GitHub Desktop.
Save blankg/d5537a458b55b9d15cb4fd78258ad840 to your computer and use it in GitHub Desktop.
For RN >= 0.57 please look at https://github.com/blankg/rn-webview-bridge-sample-new/blob/master/resources/index.html. Provides a sample implementation for sending and receiving messages to and from the React-Native WebView (using postMessage/onMessage WebView API).
/**
* Created by Guy Blank on 3/9/17.
*
* This is a sample provides an API to send & receive messages to and from the React-Native WebView (using postMessage/onMessage WebView API).
* A sample project that uses the bridge is available here https://github.com/blankg/rn-webview-bridge-sample
*
* webViewBridge.send('functionToInvoke', {mydata: 'test'}, function(){console.log('success')},function(){console.log('error')});
*
* The API is designed to be similar to the Cordova exec API so migration to it should be almost seamless.
* The API also provides solution to a React-Native WebView bug in iOS which causes sending consecutive postMessage calls to override each other.
*
* Handling message on the React-Native side:
* <WebView
* ref={webview => { this.myWebView = webview; }}
* onMessage={this.onWebViewMessage}
* />
*
* onWebViewMessage(event) {
* // post back reply as soon as possible to enable sending the next message
* this.myWebView.postMessage(event.nativeEvent.data);
*
* let msgData;
* try {
* msgData = JSON.parse(event.nativeEvent.data);
* }
* catch(err) {
* console.warn(err);
* return;
* }
*
* // invoke target function
* const response = this[msgData.targetFunc].apply(this, [msgData]);
* // trigger success callback
* msgData.isSuccessfull = true;
* msgData.args = [response];
* this.myWebView.postMessage(JSON.stringify(msgData))
* }
*
*/
(function(){
var promiseChain = Promise.resolve();
var promises = {};
var callbacks = {};
var init = function() {
const guid = function() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
}
return s4() + s4() + "-" + s4() + "-" + s4() + "-" + s4() + "-" + s4() + s4() + s4();
}
window.webViewBridge = {
/**
* send message to the React-Native WebView onMessage handler
* @param targetFunc - name of the function to invoke on the React-Native side
* @param data - data to pass
* @param success - success callback
* @param error - error callback
*/
send: function(targetFunc, data, success, error) {
success = success || function(){};
error = error || function () {};
var msgObj = {
targetFunc: targetFunc,
data: data || {},
msgId: guid(),
};
var msg = JSON.stringify(msgObj);
promiseChain = promiseChain.then(function () {
return new Promise(function (resolve, reject) {
console.log("sending message " + msgObj.targetFunc);
promises[msgObj.msgId] = {resolve: resolve, reject: reject};
callbacks[msgObj.msgId] = {
onsuccess: success,
onerror: error
};
window.postMessage(msg);
})
}).catch(function (e) {
console.error('rnBridge send failed ' + e.message);
});
},
};
window.document.addEventListener('message', function(e) {
console.log("message received from react native");
var message;
try {
message = JSON.parse(e.data)
}
catch(err) {
console.error("failed to parse message from react-native " + err);
return;
}
//resolve promise - send next message if available
if (promises[message.msgId]) {
promises[message.msgId].resolve();
delete promises[message.msgId];
}
//trigger callback
if (message.args && callbacks[message.msgId]) {
if (message.isSuccessfull) {
callbacks[message.msgId].onsuccess.apply(null, message.args);
}
else {
callbacks[message.msgId].onerror.apply(null, message.args);
}
delete callbacks[message.msgId];
}
});
};
init();
}());
@blankg
Copy link
Author

blankg commented Jan 4, 2018

Created a sample project that uses the bridge https://github.com/blankg/rn-webview-bridge-sample

@neilhamilton
Copy link

@blankg this helped me huge

@EvDevNinja
Copy link

EvDevNinja commented Apr 26, 2018

I've added support for async Promises (React Native Side) here, thanks @blankg for the code!
https://gist.github.com/EvDevNinja/f3979e00c5f0734297fae5ed79f850b8

@mrikirill
Copy link

Good job!!! It works perfect for me!

@Nixen85
Copy link

Nixen85 commented Aug 16, 2018

Thx, it worked for me, but I had to change

window.postMessage(msg); to window.postMessage(msg, '*');

otherwise I got the error

“Failed to execute 'postMessage' on 'Window': 2 arguments required, but only 1 present.”

@ap050492
Copy link

Hi all,

I tried with WebViewBridge.js in my project but it's not working with some of the devices.
Can you please help me?

can you please find my problem in below link,
https://stackoverflow.com/questions/49444738/react-native-highcharts-call-method

@kwoktung
Copy link

good

@antonioaltamura
Copy link

this used to work with RN 0.54.0, now it doesn't work anymore..not sure what's the problem..it's a nighmare try to debug a RN webview..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment