-
-
Save blankg/d5537a458b55b9d15cb4fd78258ad840 to your computer and use it in GitHub Desktop.
| /** | |
| * 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(); | |
| }()); |
Nice @blankg Though has this been tested for android as well?
use bind in ECMAScript5
onMessage={this.onWebViewMessage.bind(this)}
Created a sample project that uses the bridge https://github.com/blankg/rn-webview-bridge-sample
@blankg this helped me huge
I've added support for async Promises (React Native Side) here, thanks @blankg for the code!
https://gist.github.com/EvDevNinja/f3979e00c5f0734297fae5ed79f850b8
Good job!!! It works perfect for me!
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.”
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
good
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..
Could you show an example to use
promisein webview communicated with RN? @blankgAnd should I worry about the support of
promisein webview?