Fixing React Native WebView’s postMessage for iOS

The error that should have never been.
yarn add https://github.com/react-native-community/react-native-webview
react-native link react-native-webview

The Solution 💡

If you care more about getting this solved right now than how it works, this section is for you.

Caveats 🤕

The rn-webview package works by directing window.postMessage traffic to history.pushState instead. While React Native’s iOS implementation cannot handle window.postMessage correctly, it can handle navigation state changes. Because of this, the navigation state change event is the channel through which messages are transferred between the WebView and the native application.

The Implementation 🔨

Export 🚢

First and foremost, the ref prop of WebView is a particularly important one. Because of this, we don’t want the user to lose access to it. We start the package with a forwardRef implementation, where WebViewPostMessage is the class name used for this package.

Render 🎨

The output of this component is going to be the React Native internal implementation of WebView, with a few tweaks. We aren’t going to give it the forwardedRef prop, because that is only used to give the parent access to the ref and is totally meaningless to the internal WebView. Most importantly, we aren’t going to give it the onMessage prop, because that is the source of all of our problems — it’s not supported by iOS!

Ref 👋

When the internal WebView gives us its ref, we store it on the instance (this.ref = ref) for use later. If the parent requested the ref as well, we forward it.

Inject window.postMessage 💉

Now, a custom implementation of window.postMessage needs to exist on any page in the WebView. Whenever the navigation state changes, if it has finished loading, we inject JavaScript into it to override what window.postMessage does.

postMessage Listener 📬

Now that we have our own window.postMessage event emitter, we need to listen for it. This is the code that goes at the top of the handleNavigationStateChange method.

onNavigationStateChange 🕵

The above covers everything we need for intercepting window.postMessage and handling it with one’s own onMessage event listener. Our original problem is already solved — onMessage works with this WebView. However, since we have overwritten the internal onNavigationStateChange listener, the parent is no longer receiving navigation state change events.

Conclusion 🔚

As a reminder, you can include the component just outlined by installing the rn-webview package from NPM. You may also fork it on GitHub. Issues and pull requests are welcome.

Senior front end engineer / charlesstover.com

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store