ReactNative - Webview does not inject JavaScript on Android

I am having trouble getting Webview on ReactNative to execute the entered JavaScript on a physical Android device. I combed the network as far as I could in the last 2 days and still have not found a solution. The test results are as follows:

  • iOS simulator - All is well
  • iPhone is good
  • Android simulator - all is well
  • Physical devices, Sony Xperia Z2, Sony Xperia Z5 Compact and LG G4 - NOTHING

My Webview is defined as follows:

<WebView style={styles.webView} source={{ html: html, baseUrl: 'web/' }} injectedJavaScript={'render(' + JSON.stringify(this.state.data) + ');'} javaScriptEnabledAndroid={true} scrollEnabled={false} bounces={false} renderLoading={() => <LoadingIndicator />} /> 

I tried to specify javaScriptEnabled , but to no avail. I also tried fewer scripts just to color the elements on the page or send a message back to the application using window.postMessage , but nothing happens. I need to enter data in HTML, which will display graphs for me based on the data provided. My last resort is to manually create the HTML code with the data added as part of the markup provided by Webview, but I really want it to be simple and simple to work out as it should .

I use the latest version of ReactNative (0.41), and Android 6+ works on phones.

+5
source share
2 answers

Well, leaving this question open for some time and finding a (not very elegant) solution to the problem, I decided to share what I ended up with:

  • I announced that HTML is passed to the WebView in a constant line in the following lines: const html = '<html>...<script>...[INJECTEDSCRIPT]</script></html>';
  • I retrieved the data in the componentDidMount() event of the React component life cycle and set a state variable for it using this.setState({ data: retrievedData });
  • This, of course, forced the component to redisplay itself, after which I now have the data available to "go" to the WebView
  • Seeing that I could not find any elegant way to use the injectedJavaScript property to work the way I want it (as indicated in the question), I resorted to replacing the [INJECTEDSCRIPT] value in an HTML constant with serialized data.

Not the most elegant solution, I know, but this is the only thing that I could reliably work with many devices and configurations of the emulator. An example edited for brevity as shown below:

 const html = ` <!DOCTYPE html> <html> <head>...</head> <body>...</body> <script> var render = function (data) { ... }; [INJECTEDSCRIPT] </script> </html>`; export class GraphComponent extends Component { constructor(props) { super(props); this.state = {}; } componentDidMount = () => { SERVICE.getData().done((data) => { this.setState({ data: data }); }); } render = () => { if (!this.state.data) return <LoadingIndicator />; let serializedData = JSON.stringify(this.state.data); return <WebView style={styles.webView} source={{ html: html.replace('[INJECTEDSCRIPT]', 'render(' + serializedData + ');'), baseUrl: 'web/' }} scrollEnabled={false} bounces={false} renderLoading={() => <LoadingIndicator />} />; } } 
+3
source

I just discovered that Android WebView seems to inject any JS as one line , even if it includes line breaks. This means that missing semicolons can definitely cause problems or, in my case, comments limited to // . Using /* and */ for comments, my working JavaScript worked again.

+2
source

Source: https://habr.com/ru/post/1264849/


All Articles