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's injectedJavaScript prop doesn't produce any effect #196

Closed
shirakaba opened this issue May 9, 2018 · 2 comments
Closed

WebView's injectedJavaScript prop doesn't produce any effect #196

shirakaba opened this issue May 9, 2018 · 2 comments

Comments

@shirakaba
Copy link
Contributor

shirakaba commented May 9, 2018

Description

Related to #195 . The injectedJavaScript prop should allow one to inject JS into a webpage (on iOS, one gets the choice of injecting before or after page load, but React Native doesn't seem to give that amount of granularity). I'd expect to see the page transition from saying "Test before" to "Test after". However, it doesn't produce any change in the web-page at all.

I have tried this both with a static HTML page and dynamic pages loaded over HTTP and HTTPS. I have furthermore tried both with and without NSAllowsArbitraryLoadsInWebContent set to YES.

Reproduction Steps and Sample Code

The UIExplorer WebView examples can be used to reproduce this, or the following minimal example can be copied:

'use strict';

var React = require('React');
var ReactNative = require('react-native');
var {
  StyleSheet,
  Button,
  View,
  WebView,
} = ReactNative;

class InjectJS extends React.Component {
  webview = null;
  render() {
    return (
      <View>
        <WebView
          ref={webview => {
            this.webview = webview;
          }}
          injectedJavaScript={"document.write(\"<h1>Test after</h1>\");"}
          style={{
            backgroundColor: 'rgba(255,255,255,0.8)',
            height: 300,
          }}
          source={{ html: "<h1>Test before</h1>" }}
          scalesPageToFit={true}
        />
      </View>
    );
  }
}

var styles = StyleSheet.create({
  buttons: {
    flexDirection: 'row',
    height: 30,
    backgroundColor: 'black',
    alignItems: 'center',
    justifyContent: 'space-between',
  }
})

Additional Information

  • React Native version: react-native-macos v0.16.1
  • Platform: macOS
  • Development Operating System: macOS
  • Dev tools: Xcode 9.3

Solution

Will need to revisit this, but I'm beginning to suspect that the native code is outdated. I'm seeing a few problems:

RCTWebView.m passes on the injectedJavaScript prop to a call tostringByEvaluatingJavaScriptFromString() during the decidePolicyForNavigationAction() block.

  • stringByEvaluatingJavaScriptFromString() is a method used for the deprecated UIWebView rather than the up-to-date WKWebView. For a start, this would be better replaced by WKWebView evaluateJavaScript() (although the former is sync and the latter is async, so that adds differences; but see my final point for a solution anyway).

  • decidePolicyForNavigationAction() called when the app has "decided whether to allow or cancel the navigation". I fear that any JS executed in here might correspond to the previously-held page rather than being applied to the incoming page, and in any case that it certainly gives no control over whether to inject the JS before beginning, or after completing, page load.

  • injectedJavaScript would be much better – and ideally – handled by allowing the WKWebView to be initialised with a WKUserContentController that accepts a script to pass into its addUserScript() method. I've had a lot of success with this API.

Is this on the roadmap for the next update, or is help needed in this area?

@shirakaba
Copy link
Contributor Author

Looks like my build/cache must have been screwing up, because I found that the injected JS did begin to work today.

In any case, having been alarmed by the fact that the RN core is still using the hideously outdated UIWebView, I decided to make a macOS fork of the community-favourite CRAlpha/react-native-wkwebview. Until RN do decide to merge that into core, it'll remain as a third-party plugin. But thanks to this fork, making a macOS port will be trivial to get up-to-date if their repo ever does get merged.

My port does not yet expose an API for WKUserContentController.addUserScript(), but it's on my hitlist.

@ptmt
Copy link
Owner

ptmt commented May 14, 2018 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants