[SOLVED] Local javascript in webview

I understood running local javascript in a WebView is a bit of a pain in RN.
https://github.com/facebook/react-native/issues/8089

All the solution I found talks about handling the problem in android/ios directories. We haven’t those in Expo apps, so there is a known way to make this work?

I really need this, I have to give up with RN for this project if this is currently unsupported. Could someone spend a minute with this issue :smile: ? To be more specific I need to show a vis.js graph in my webview.
Some details:
My webview works correctly when I launch on a real device a debug build using react-native-scripts android. It doesn’t in release build. Maybe it’s just the assets path that changes (html,css, client side js). How can I investigate this?

Hi @alfredopacino - you can detach in order to get android/ios directories - see our guide here for more details: https://docs.expo.io/versions/v27.0.0/expokit/detach .

Another option would be to request your vis.js script over-the-air in your webview rather than bundling it with your app, which would be simpler, but would require that users have an internet connection before your graph would load.

Honesly I still do not get what’s the problem with local (client side) javascript

I would avoid detaching, and my app should be offline.

@alfredopacino - the root problem, I believe, is that it’s hard for the react native packager to view JS files as assets that are not part of the main project JS bundle.

This may not work, but have you tried doing something like saving the entire contents of vis.js as a string inside of your project and then importing it statically into your webview?

Import statically could be a way, by I tried and still doesn’t work (I escaped all the back-ticks in the code), I sure there is a way to make it work: Some plain client side javascript works, can’t see a reason this library don’t have to.

Anyway, there is a way I can catch all the WebView console errors and logs? I suspect renderError do not doing that the way I’m using it.

I tried to make a snack hoping someone way more skilled than me would help…the browser crashes when I upload a ~2MB single js file :slight_smile:

This is the whole code

import React, { Component } from 'react';
import { WebView, StyleSheet,ActivityIndicator } from 'react-native';
import style from "./css"
import jsGraph from './jsGraph';
import visjs from './VISJs'; //<-- this is Vis.js lib (http://visjs.org/dist/vis.js) wrapped in a <script> tag like jsGraph and backtick escaped


const fullPost = `
<html>
<head>
</head>
<body>
<div id="mynetwork"></div>
</body>
</html>`;

export default class App extends Component {
  render() {
    return (
			<WebView
				style={styles.WebViewStyle}
				source={{ html: fullPost}}
				javaScriptEnabled={true}
				domStorageEnabled={true}
				renderError={(error)=>console.log('error:'+error)}
				renderLoading={()=>{return(<ActivityIndicator style={{flex: 1,flexDirection: 'row',justifyContent: 'space-around',padding: 10}} size="large" color="#1a237e" />)}}
				startInLoadingState
			/>

		);
  }
}
const styles = StyleSheet.create({
	WebViewStyle:
		{
			justifyContent: 'center',
			alignItems: 'center',
			flex:1
			}
});

jsGraph


const jsGraph = `
<script type="text/javascript">
	// create an array with nodes
	var nodes = new vis.DataSet([
	{id: 1, label: 'Node 1'},
	{id: 2, label: 'Node 2'},
	{id: 3, label: 'Node 3'},
	{id: 4, label: 'Node 4'},
	{id: 5, label: 'Node 5'}
	]);

	// create an array with edges
	var edges = new vis.DataSet([
	{from: 1, to: 3},
	{from: 1, to: 2},
	{from: 2, to: 4},
	{from: 2, to: 5},
	{from: 3, to: 3}
	]);

	// create a network
	var container = document.getElementById('mynetwork');
	var data = {
	nodes: nodes,
	edges: edges
};
	var options = {};
	var network = new vis.Network(container, data, options);
</script>`;
export default jsGraph;

css

const css = `
<style>
body {
    background: grey;
}
#mynetwork {
      width: 600px;
      height: 400px;
      border: 1px solid lightgray;
    }
</style>
`;
export default css;

DIFFERENT OPTION: This is the solution I was talking in the second post of this thread (obiouvsly it’s a different solution than the above code). It works testing on android device in debug release, it doesn’t if I build the expo release build. Basically the solution not uses a plain javascript code, but a webpack bundled code. Really can’t tell what’s the magic webpack does in this case.

I would glad if someone would take the time of try that code.
Since now there is no real external file, it’s just a huge html file with inline javascript.
I think the problem is some unescaped/problematic characters in the lib code.

The only reliable way I found is to include all css and javascript inline in the html file.

const LocalWebURL = require('./index.html'); //with css and js inline

<WebView
			source={LocalWebURL}
			javaScriptEnabled={true}
			domStorageEnabled={true}
			mixedContentMode='always'
			renderError={(error)=>console.log('error:',error)}
			ref={webview => { this.myWebView = webview; }}
	/>
1 Like

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.