Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WebView] onMessage failing when there are JS warnings and errors on the page #10865

Closed
raiderrobert opened this issue Nov 10, 2016 · 92 comments
Closed
Labels
Component: WebView Related to the WebView component. Platform: iOS iOS applications. Resolution: Locked This issue was locked by the bot.

Comments

@raiderrobert
Copy link

raiderrobert commented Nov 10, 2016

Description

I'm receiving this error (same as screenshot below):

Setting onMessage on a WebView overrides existing values of window.postMessage, 
but a previous value was defined.

screen shot 2016-11-10 at 3 33 31 pm

That specific error message is found in the code base here: https://github.com/facebook/react-native/blob/master/React/Views/RCTWebView.m#L286

Implementation

I followed the example at this link for onMessage at this link: http://facebook.github.io/react-native/releases/0.37/docs/webview.html#examples

I made a callable respondToOnMessage and injected some JavaScript.

class MessagingTest extends React.Component {

    respondToOnMessage = e =>{
        console.log(e);
    };

    render() {
        const jsCode = `window.postMessage('test');`;

        return (
        <WebView
        injectedJavaScript={jsCode}
        source={uri: 'https://www.foo.com/'}}
        onMessage={this.respondToOnMessage}
        />
        )
    }
}

Reproduction

I load the app with this example and I have it pointed to a website (rather not say which one. Sorry.) And the website is emitting 2 errors into the Chrome console when I go there.

(index):994 A Parser-blocking, cross-origin script, http://example.com/thing.js, is invoked via document.write. This may be blocked by the browser if the device has poor network connectivity.

widgets.js:8 Uncaught TypeError: Cannot set property '[object Array]' of undefined(…)

Other websites like google.com and github.com are just fine. If you want to replicate it, change the uri to yahoo.com

Additional Information

  • React Native version: 0.37
  • Platform: iOS 10.1, iPhone 6 emulator
  • Operating System: Mac OSX Sierra 10.12.1
@raiderrobert
Copy link
Author

I should also add that I attempted to replicate the error on Android 7.0 and API 24 using a Nexus_5x emulator, and I got NO error. So this seems to be a platform specific error.

@hramos hramos added the Platform: iOS iOS applications. label Nov 10, 2016
@sreucherand
Copy link

I'm getting the same error. Seems like this exception is thrown when window.postMessage has been overwritten. But since webViewDidFinishLoad is called multiple times, it tries to overwrite window.postMessage over and over. Not sure though. Can we have you expertise @jacobp100?

@jacobp100
Copy link
Contributor

jacobp100 commented Nov 11, 2016

It’s because the page you’re visiting is overriding postMessage, which may be due to a shim. Showing an error was chosen over invoking the shim’s value of postMessage when you call the value of postMessage that we set.

I thought I’d made it easier to workaround this problem, but it looks like that won’t work. The best you can do at the moment, which is an awful hack, is,

injectedJavaScript="window.postMessage = String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage');"

Or just fork the project and remove the code you pointed to. Whatever’s easiest for you!

Ping @satya164 for input on how to resolve.

@sreucherand
Copy link

Well, when I try String(window.postMessage) === String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage') on the page I visit, it returns true, so I am guessing postMessage has not been overridden.

@jacobp100
Copy link
Contributor

Oh I see. The JS is injected after postMessage is overwritten. Your best bet is to fork it then, and I’ll see what I can do about getting this fixed! Sorry. :(

@persyl
Copy link

persyl commented Nov 20, 2016

I have same error, without injecting any javascript to WebView - just setting WebView-properties:

source={require('../lib/html/somefile.html')}
onMessage={() => console.log('Hello World')}

and in my ../lib/html/somefile.html' I have javascript code doing both window.postMessage() and document.addEventListener("message",.......

Everything worked fine when I had the HTML in a variable "someHtml", like:
source={{html: someHtml}}

So difference seem to be when changing source to HTML-file instead of HTML-string.

Still for me I had other reasons, not related to this, why I really need to read HTML from file instead of string so it would be great to get this issue fixed.

@cbcye
Copy link

cbcye commented Nov 20, 2016

+1, still has this problem

@jacobp100
Copy link
Contributor

There is an ongoing discussion in #10941 for the best way to go forward with this.

It won't be in the next release or probably the release after. If you need this fixed now, fork the project and use the fix in the PR.

@lealife
Copy link

lealife commented Dec 19, 2016

+1, I'm getting the same error. When there is a iframe on web, it occurs the same error

@varhp
Copy link

varhp commented Dec 21, 2016

+1,encounter this problem

@jacobp100
Copy link
Contributor

Again, there is a pr for this. We're aware this problem is affecting a lot of people.

@edencakir
Copy link

+1 getting the same error.

@kyle-ilantzis
Copy link

kyle-ilantzis commented Dec 31, 2016

injectedJavascript should instead be the following

(function() {
  var originalPostMessage = window.postMessage;

  var patchedPostMessage = function(message, targetOrigin, transfer) { 
    originalPostMessage(message, targetOrigin, transfer);
  };

  patchedPostMessage.toString = function() { 
    return String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage'); 
  };

  window.postMessage = patchedPostMessage;
})();

And then it works! 😄

And if any one is interested, in my code instead of writing a giant string I did the following

const patchPostMessageFunction = function() {
  var originalPostMessage = window.postMessage;

  var patchedPostMessage = function(message, targetOrigin, transfer) { 
    originalPostMessage(message, targetOrigin, transfer);
  };

  patchedPostMessage.toString = function() { 
    return String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage');
  };

  window.postMessage = patchedPostMessage;
};

const patchPostMessageJsCode = '(' + String(patchPostMessageFunction) + ')();';

...

<WebView injectedJavaScript={patchPostMessageJsCode} />

@mschipperheyn
Copy link

@kyle-ilantzis tried this with RN 0.38.1, but still get the Red Screen. What version of RN are you on?

@kyle-ilantzis
Copy link

@mschipperheyn I am using RN 0.39.0

The ios webview code between 0.39 and 0.38 is not different so it is odd you still get the red screen.

https://github.com/facebook/react-native/blob/0.39-stable/React/Views/RCTWebView.m#L280

https://github.com/facebook/react-native/blob/0.38-stable/React/Views/RCTWebView.m#L280

@abeauvois
Copy link

Same issue with RN 0.40, as soon as we add 'onMessage' props to the WebView.

@hadrienj
Copy link

hadrienj commented Mar 9, 2017

Same issue with RN 0.42 with a WebView (without js injection) when I load PouchDB (6.1.2).

@skrobek
Copy link

skrobek commented Mar 21, 2017

@kyle-ilantzis I'm trying your solution with RN 0.42 but after using it I can't see onMessage callback:

pushCredentials = () => {
  if (this.webview) {
    this.webview.postMessage('Post message triggered');
  }
}


onMessage = (e) => {
    this.setState({ postMessage: e.nativeEvent.data });
};

// in render method
<WebView
    ref={(ref) => { this.webview = ref; }}
    source={{ uri}}
    injectedJavaScript={patchPostMessageJsCode}
    onMessage={this.onMessage}
/>

@kyle-ilantzis
Copy link

@skrobek Do you mean pushCredentials() no longer causes onMessage() to be called?

  1. Should it not be:
    onMessage={this.onMessage.bind(this)}

  2. I never thought that when posting a message from react-native to the webview the webview would call its own onMessage. I thought onMessage is only called when JS code in the webview calls window.postMessage(...)

@skrobek
Copy link

skrobek commented Mar 21, 2017

@kyle-ilantzis Look at the docs example:

class MessagingTest extends React.Component {
  webview = null

  state = {
    messagesReceivedFromWebView: 0,
    message: '',
  }

  onMessage = e => this.setState({
    messagesReceivedFromWebView: this.state.messagesReceivedFromWebView + 1,
    message: e.nativeEvent.data,
  })

  postMessage = () => {
    if (this.webview) {
      this.webview.postMessage('"Hello" from React Native!');
    }
  }

  render(): ReactElement<any> {
    const {messagesReceivedFromWebView, message} = this.state;

    return (
      <View style={[styles.container, { height: 200 }]}>
        <View style={styles.container}>
          <Text>Messages received from web view: {messagesReceivedFromWebView}</Text>
          <Text>{message || '(No message)'}</Text>
          <View style={styles.buttons}>
            <Button text="Send Message to Web View" enabled onPress={this.postMessage} />
          </View>
        </View>
        <View style={styles.container}>
          <WebView
            ref={webview => { this.webview = webview; }}
            style={{
              backgroundColor: BGWASH,
              height: 100,
            }}
            source={require('./messagingtest.html')}
            onMessage={this.onMessage}
          />
        </View>
      </View>
    );
  }
}

@kyle-ilantzis
Copy link

@skrobek Oh no 😱

My objective was to have the JS code in the webview talk to react-native. It was not to have react-native talk to itself through a webview.

patchPostMessage achieved my objective, no more red screen on ios when setting the onMessage property of a webview. JS code in an IOS webview could then talk to react-native

@skrobek
Copy link

skrobek commented Mar 21, 2017

@kyle-ilantzis Yeah. Now I have huge problem because docs cause red screen and your solution helps with the red screen but block webview.postMessage - no idea what to do ;-)

@davidhellsing
Copy link

davidhellsing commented Mar 24, 2017

You could wait for the onLoad before passing onMessage into the component (passing null until the onLoad triggers).

It worked for us, but we had to implement a simple queue in the webview that collects posts until the onLoad has triggered, which then triggers another onLoad inside the webview using injectJavaScript...

  onLoad(e) {
    // onload is called multiple times...
    if ( this.state.loaded ) {
      return
    }
    this.setState({ loaded: true }, () => this.bridge.injectJavaScript('window.onLoad()'))
  }
  onMessage(payload) {
    console.log('got message from web view', payload)
  }
  render() {
    return (
      <WebView
        onLoad={this.onLoad}
        ref={n => this.bridge = n} 
        source={require('../assets/bridge.html')} 
        javaScriptEnabled={true} 
        onMessage={this.state.loaded ? this.onMessage.bind(this) : null} 
      />
    )
  }

@kyle-ilantzis
Copy link

@davidhellsing interesting to use the webview onLoad. With the injectedJavascipt solution I still needed to implement a queue in the webview

@axten
Copy link

axten commented Apr 13, 2017

The Workarounds are not working for me.
Is someone working on an fix for that?

@davidhellsing
Copy link

If you feel brave, use a shell script to rename the native postMessage:

sed -i '' '/@"window.originalPostMessage = window.postMessage;"/d' node_modules/react-native/React/Views/RCTWebView.m
sed -i '' 's/  "window.postMessage = function(data) {/@"window.nativePostMessage = function(data) {/' node_modules/react-native/React/Views/RCTWebView.m
sed -i '' '/"window.originalPostMessage = window.postMessage," +/d' node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/webview/ReactWebViewManager.java
sed -i '' 's/"window.postMessage = function(data) {" +/"window.nativePostMessage = function(data) {" +/' node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/webview/ReactWebViewManager.java

After running this script (you will need to do it after each yarn npm install), you can simply use:

window.nativePostMessage('it works')

inside your webView. IMO, this should be done a long time ago... there is a PR here for basically the same thing: https://github.com/facebook/react-native/pull/12997/files?diff=split

@0x6e6562
Copy link

@davidhellsing Nice patch :-)

This appears to be working for me on iOS with RN 0.44 (haven't tried it on Android yet).

ivank added a commit to ivank/react-native that referenced this issue Jul 19, 2018
The current way we're testing if postMessage has been changed is no
longer valid. Lodash has already changed the way they test agianst this,
as it no longer works in blink (thow continiues to work in webkit)

In chrome browser (Version 65.0.3325.181 (Official Build) (64-bit)) console type:

```js
String(window.postMessage) === String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage')
```

It still works in safari (Version 11.0.3 (13604.5.6))

A simplified version of how lodash are testing aginst it
https://github.com/lodash/lodash/blob/4.0.1-npm-packages/lodash.isnative/index.js

With a simpler description about this method can be found here:
https://davidwalsh.name/detect-native-function

Running:

```js
RegExp('^' +
  String(Object.prototype.toString)
  .replace(/[.*+?^${}()|[\]\/\\]/g, '\\$&')
  .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
).test(String(window.postMessage))
```

Works correctly in both chrome and safari.

Affected issues:

facebook#10865 - some hacks were
seggested here to sidestep this issue. This PR should fix it outright
@schlaegerz
Copy link

No matter what I do, if I try to implement onMessage it breaks the website.

I am trying to render a meteor app in the Webview, and it depends on postMessage just working normally.

This would be solved if we could just override the name of the postMessage, like lettings us specify a namespace window.reactNative.postMessage or just change it to window.RNPostmessage it doesn't even need to be a default, but giving the option to change it would fix all these problems.

@laukaichung
Copy link

@jneuendorf
You are right. I have a quill editor loaded in the WebView. The problem only occurs when the content contains a youtube video.

@Titozzz
Copy link
Collaborator

Titozzz commented Sep 9, 2018

Hi there, we are migrating all the WebView issues to the new repository https://github.com/react-native-community/react-native-webview. Correct me if I'm wrong but this does not seem to happen with the new WKWebview implementation. If it does, feel free to open an issue directly on the new repository and link that issue to it!
Thanks,

@laukaichung
Copy link

laukaichung commented Sep 13, 2018

@Titozzz
I use react-native-navigation and react-native-link no longer applies changes on MainApplication.java for Android. When I install libraries I have to add the packages manually.

Do I need to add the webview package to the createAdditionalReactPackages() method?
I ran react-native link react-native-webview but there are no changes on the file.

@Titozzz
Copy link
Collaborator

Titozzz commented Sep 13, 2018

@stonecold123 please open an issue on the new repo

@quisido
Copy link

quisido commented Sep 23, 2018

For anyone still struggling with this, I released rn-webview on NPM to solve this exact problem (open-sourced on GitHub). My team and myself are unable or unwilling to eject from our Expo implementation in order to use the community edition linked a few posts above. If you are able to do so, I'd recommend that option. If you want to maintain a purely JavaScript, out-of-the-box Expo experience, the rn-webview package is for you.

I wrote a walkthrough for how it works on Medium. Of course the implementation has to have drawbacks, and the way it works may not be acceptable for your use case. The biggest deal is that, instead of relying on native window.postMessage function, it instead manipulates the history (history.pushState) so that it can listen to the navigation state change event (which is supported by both Android and iOS). Feel free to suggest better implementations in the Issues for the repo or fork and adjust not altering the navigation state is crucial to your project.

Hope this helps!

@Titozzz
Copy link
Collaborator

Titozzz commented Sep 24, 2018

@CharlesStover To goal of the community repo is to fix theses issues that were never fixed. The slimmening should allow everyone to move faster. We, of course, hope that expo will choose to add all the slimmening packages into their releases so that you don't have to depend on such workarounds

@Titozzz Titozzz closed this as completed Sep 24, 2018
@AdamZaczek
Copy link

injectedJavascript should instead be the following

(function() {
  var originalPostMessage = window.postMessage;

  var patchedPostMessage = function(message, targetOrigin, transfer) { 
    originalPostMessage(message, targetOrigin, transfer);
  };

  patchedPostMessage.toString = function() { 
    return String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage'); 
  };

  window.postMessage = patchedPostMessage;
})();

And then it works! 😄

And if any one is interested, in my code instead of writing a giant string I did the following

const patchPostMessageFunction = function() {
  var originalPostMessage = window.postMessage;

  var patchedPostMessage = function(message, targetOrigin, transfer) { 
    originalPostMessage(message, targetOrigin, transfer);
  };

  patchedPostMessage.toString = function() { 
    return String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage');
  };

  window.postMessage = patchedPostMessage;
};

const patchPostMessageJsCode = '(' + String(patchPostMessageFunction) + ')();';

...

<WebView injectedJavaScript={patchPostMessageJsCode} />

You man are my hero! This is so simple and eloquent. It works for Expo 31 even when using iframes

@olegongit
Copy link

For me it helped to use 'useWebKit' prop on a WebView.

harutyundr added a commit to addonslab/react-native-autoheight-webview that referenced this issue Feb 10, 2019
@princeTPG
Copy link

princeTPG commented Feb 12, 2019

This issue will not occur is you use "useWebKit" prop of webview, that will use WK webview instead of UI webview in case of IOS.
But in case if you don't want to use WK webview, then below is the sample JS code that you can inject in you Webview with "injectedJavaScript" prop.

  `(function () {
      let originalPostMessage = window.postMessage;
      let patchedPostMessage = function(message, targetOrigin, transfer, ...other) { 
        originalPostMessage(message, targetOrigin, transfer, ...other);
      };

      patchedPostMessage.toString = function() { 
        return String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage');
      };

      window.postMessage = patchedPostMessage;
    })()`

The above code did nothing just patched window.postMessage function, the above issue will not appear.

@Angelk90
Copy link

Angelk90 commented Apr 1, 2019

@AdamZaczek , @princeTPG :

I can't get it to work properly, you can give an example that can work on https://snack.expo.io?

I did something like that, but it seems that it doesn't work anymore.

Code:

render() {
    const jsCodeOpenload = `
        (function ready() {
          function whenRNPostMessageReady(cb) {
            if (postMessage.length === 1) cb();
            else setTimeout(function() { whenRNPostMessageReady(cb) }, 100);
          }
          whenRNPostMessageReady(function() {
            postMessage(document.getElementById('olvideo_html5_api').innerHTML);
          });
        })();`;
    return (
      <View>
        {this.state.urlOpenload != '' && (
          <WebView
            source={{
              uri: this.state.urlOpenload,
            }}
            onMessage={evt => {
              this.setState({ code: evt.nativeEvent.data });
            }}
            injectedJavaScript={jsCodeOpenload}
            javaScriptEnabled
            style={{ flex: 1 }}
          />
        )}
      </View>
    );
  }

onMessage seems to receive nothing more, even if it worked before.

@TfADrama
Copy link

This issue will not occur is you use "useWebKit" prop of webview, that will use WK webview instead of UI webview in case of IOS.
But in case if you don't want to use WK webview, then below is the sample JS code that you can inject in you Webview with "injectedJavaScript" prop.

  `(function () {
      let originalPostMessage = window.postMessage;
      let patchedPostMessage = function(message, targetOrigin, transfer, ...other) { 
        originalPostMessage(message, targetOrigin, transfer, ...other);
      };

      patchedPostMessage.toString = function() { 
        return String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage');
      };

      window.postMessage = patchedPostMessage;
    })()`

The above code did nothing just patched window.postMessage function, the above issue will not appear.

The patched script makes my onMessage to be always called twice in iOS when i do a click event...
The useWebKit prop was the only way, at least for now...

@kenobi91
Copy link

If you still have this issue you can use code from above, to prevent this error like this:

`const patchPostMessageFunction = function() {
var originalPostMessage = window.postMessage;

var patchedPostMessage = function(message, targetOrigin, transfer) {
originalPostMessage(message, targetOrigin, transfer);
};

patchedPostMessage.toString = function() {
return String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage');
};

window.postMessage = patchedPostMessage;
};`

Then you can append your own JS injection code like this:

<WebView injectedJavaScript={'(' + String(patchPostMessageFunction) + ')();' + injectedJavaScript}/>

This will prevent error from above but also this will prevent in some cases to use window.postMessage from your injected JS code. To go around this just wrap window.postMessage(msg) in timeout like this:
setTimeout(() => { window.postMessage(JSON.stringify(postMessage)); }, 100);

@Rafaell416
Copy link

injectedJavascript should instead be the following

(function() {
  var originalPostMessage = window.postMessage;

  var patchedPostMessage = function(message, targetOrigin, transfer) { 
    originalPostMessage(message, targetOrigin, transfer);
  };

  patchedPostMessage.toString = function() { 
    return String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage'); 
  };

  window.postMessage = patchedPostMessage;
})();

And then it works! 😄

And if any one is interested, in my code instead of writing a giant string I did the following

const patchPostMessageFunction = function() {
  var originalPostMessage = window.postMessage;

  var patchedPostMessage = function(message, targetOrigin, transfer) { 
    originalPostMessage(message, targetOrigin, transfer);
  };

  patchedPostMessage.toString = function() { 
    return String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage');
  };

  window.postMessage = patchedPostMessage;
};

const patchPostMessageJsCode = '(' + String(patchPostMessageFunction) + ')();';

...

<WebView injectedJavaScript={patchPostMessageJsCode} />

Awesome man, if you come to Colombia I'll invite u some Empanadas.

@kckunal2612
Copy link

injectedJavascript should instead be the following

(function() {
  var originalPostMessage = window.postMessage;

  var patchedPostMessage = function(message, targetOrigin, transfer) { 
    originalPostMessage(message, targetOrigin, transfer);
  };

  patchedPostMessage.toString = function() { 
    return String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage'); 
  };

  window.postMessage = patchedPostMessage;
})();

And then it works! 😄

And if any one is interested, in my code instead of writing a giant string I did the following

const patchPostMessageFunction = function() {
  var originalPostMessage = window.postMessage;

  var patchedPostMessage = function(message, targetOrigin, transfer) { 
    originalPostMessage(message, targetOrigin, transfer);
  };

  patchedPostMessage.toString = function() { 
    return String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage');
  };

  window.postMessage = patchedPostMessage;
};

const patchPostMessageJsCode = '(' + String(patchPostMessageFunction) + ')();';

...

<WebView injectedJavaScript={patchPostMessageJsCode} />

Is there an updated version of this answer which will work with the new version of react-native-webview ? I am unable to receive messages in onMessage() on both iOS and Android. :(

@kckunal2612
Copy link

Is there an updated version of this answer which will work with the new version of react-native-webview ? I am unable to receive messages in onMessage() on both iOS and Android. :(

Answering my own question here for everyone else's reference -

(See - https://github.com/react-native-community/react-native-webview/releases/tag/v5.0.0)

// Apply fix for newer react-native-webview not supporting window.postMessage
const webViewFix = function() {
  window.postMessage = function(data) {
    window.ReactNativeWebView.postMessage(data);
  };
};
const windowPostMessageFix = '(' + String(webViewFix) + ')();';

const patchPostMessageFunction = function() {
  const originalPostMessage = window.postMessage;

  const patchedPostMessage = function(message, targetOrigin, transfer) {
    originalPostMessage(message, targetOrigin, transfer);
  };

  patchedPostMessage.toString = function() {
    return String(Object.hasOwnProperty).replace(
      'hasOwnProperty',
      'postMessage',
    );
  };

  window.postMessage = patchedPostMessage;
};

const patchPostMessageJsCode = '(' + String(patchPostMessageFunction) + ')();';

Make sure you call windowPostMessageFix function first and then your second function -

<WebView
 injectedJavaScript={[
                windowPostMessageFix,
                patchPostMessageJsCode
              ].join('')}

I hope it helps ! Thanks !

@DevArenaCN
Copy link

Is there an updated version of this answer which will work with the new version of react-native-webview ? I am unable to receive messages in onMessage() on both iOS and Android. :(

Answering my own question here for everyone else's reference -

(See - https://github.com/react-native-community/react-native-webview/releases/tag/v5.0.0)

// Apply fix for newer react-native-webview not supporting window.postMessage
const webViewFix = function() {
  window.postMessage = function(data) {
    window.ReactNativeWebView.postMessage(data);
  };
};
const windowPostMessageFix = '(' + String(webViewFix) + ')();';

const patchPostMessageFunction = function() {
  const originalPostMessage = window.postMessage;

  const patchedPostMessage = function(message, targetOrigin, transfer) {
    originalPostMessage(message, targetOrigin, transfer);
  };

  patchedPostMessage.toString = function() {
    return String(Object.hasOwnProperty).replace(
      'hasOwnProperty',
      'postMessage',
    );
  };

  window.postMessage = patchedPostMessage;
};

const patchPostMessageJsCode = '(' + String(patchPostMessageFunction) + ')();';

Make sure you call windowPostMessageFix function first and then your second function -

<WebView
 injectedJavaScript={[
                windowPostMessageFix,
                patchPostMessageJsCode
              ].join('')}

I hope it helps ! Thanks !

This did solve the issue with the red screen, but when I tried to post data back from my frontend code calling window.postMessage('some stuff'. '*') I got error TypeError: undefined is not an object (evaluating 'window.ReactNativeWebView.postMessage') Any ideas?

@kckunal2612
Copy link

Is there an updated version of this answer which will work with the new version of react-native-webview ? I am unable to receive messages in onMessage() on both iOS and Android. :(

Answering my own question here for everyone else's reference -
(See - https://github.com/react-native-community/react-native-webview/releases/tag/v5.0.0)

// Apply fix for newer react-native-webview not supporting window.postMessage
const webViewFix = function() {
  window.postMessage = function(data) {
    window.ReactNativeWebView.postMessage(data);
  };
};
const windowPostMessageFix = '(' + String(webViewFix) + ')();';

const patchPostMessageFunction = function() {
  const originalPostMessage = window.postMessage;

  const patchedPostMessage = function(message, targetOrigin, transfer) {
    originalPostMessage(message, targetOrigin, transfer);
  };

  patchedPostMessage.toString = function() {
    return String(Object.hasOwnProperty).replace(
      'hasOwnProperty',
      'postMessage',
    );
  };

  window.postMessage = patchedPostMessage;
};

const patchPostMessageJsCode = '(' + String(patchPostMessageFunction) + ')();';

Make sure you call windowPostMessageFix function first and then your second function -

<WebView
 injectedJavaScript={[
                windowPostMessageFix,
                patchPostMessageJsCode
              ].join('')}

I hope it helps ! Thanks !

This did solve the issue with the red screen, but when I tried to post data back from my frontend code calling window.postMessage('some stuff'. '*') I got error TypeError: undefined is not an object (evaluating 'window.ReactNativeWebView.postMessage') Any ideas?

I tested my app on Lollipop and it crashes due to a WebView issue listed here -
react-native-webview/react-native-webview#858

As a result, our company is now moving away from React Native for Android. Sadly, there are too many breaking changes and too many security vulnerabilities in third party libraries.

@facebook facebook locked as resolved and limited conversation to collaborators Dec 11, 2019
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Dec 11, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Component: WebView Related to the WebView component. Platform: iOS iOS applications. Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

Successfully merging a pull request may close this issue.