usage on expo as there is no android_asset folder
tshiamor-adft opened this issue · 5 comments
Thanks for such a wrapper, however I am unclear on how to use this with expo, as there is no separate android + ios folder when using expo-cli. already tried adding a new android_asset/index.html to the assets folder, however that didn't work. Would appreciate a bit of explanation for beginners, since the readme illustrates useage in a react-native structure and none is shown for expo project structure, thanks a lot.
I will have a look at it and i will write a step by step tutorial for expo.
finally got it working in expo by making a sort of dirty workaround.
had to modify the index.js in the node_modules/react-native-echarts-wrapper/src/, and reference the index.html in the same folder.
Hope there is a better approach or solution for expo on android, as this is just a temporary approach, rebuilding the project would probably replace with the original file as this is within the node_modules.
import React, { Component } from 'react';
import { View, Platform } from 'react-native';
import PropTypes from 'prop-types';
/* eslint-enable */
import * as jsBuilder from './jsBuilder';
import {WebView} from 'react-native';
let WebViewExternalPackage = WebView;
class ECharts extends Component {
static propTypes = {
onData: PropTypes.func,
baseUrl: PropTypes.string,
legacyMode: PropTypes.bool,
canvas: PropTypes.bool,
onLoadEnd: PropTypes.func
};
static defaultProps = {
baseUrl: "",
onData: () => {},
legacyMode: false,
canvas: false,
onLoadEnd: () => {}
};
constructor(props) {
super(props);
this.onGetHeight = null;
this.callbacks = {};
const { baseUrl } = props;
this.html = `
<!DOCTYPE html>
<html lang="de">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=3, minimum-scale=1, user-scalable=no">
<style type="text/css">
html,body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
background-color:rgba(0, 0, 0, 0);
}
#main {
height: 100%;
background-color:rgba(0, 0, 0, 0);
}
</style>
<script src="${baseUrl}/echarts.min.js"></script>
</head>
<body>
<div id="main"></div>
</body>
</html>`;
}
onMessage = e => {
try {
if (!e) return null;
const { onData } = this.props;
const data = JSON.parse(e.nativeEvent.data);
if (data.types === "DATA") {
onData(data.payload);
} else if (data.types === "CALLBACK") {
/* eslint-disable no-case-declarations */
const { uuid } = data;
/* eslint-enable no-case-declarations */
this.callbacks[uuid](data.payload);
}
} catch (error) {
console.log(error);
}
};
postMessage = data => {
this.webview.postMessage(jsBuilder.convertToPostMessageString(data));
};
ID = () =>
`_${Math.random()
.toString(36)
.substr(2, 9)}`;
getOption = (callback, properties = undefined) => {
const uuid = this.ID();
this.callbacks[uuid] = callback;
const data = {
types: "GET_OPTION",
uuid,
properties
};
this.postMessage(data);
};
setOption = (option, notMerge, lazyUpdate) => {
const data = {
types: "SET_OPTION",
payload: {
option,
notMerge: notMerge || false,
lazyUpdate: lazyUpdate || false
}
};
this.postMessage(data);
};
clear = () => {
const data = {
types: "CLEAR"
};
this.postMessage(data);
};
getWebViewRef = ref => {
this.webview = ref;
};
render() {
let source;
const { baseUrl, legacyMode } = this.props;
const localUri = Expo.Asset.fromModule(require('./index.html')).uri;
if (baseUrl) {
source = {
html: this.html,
baseUrl
};
} else {
/* eslint-disable global-require */
source =
Platform.OS === "ios"
? require("./index.html")
: {'uri': localUri };
console.log(JSON.stringify(source));
/* eslint-enable global-require */
}
let isExpo = false;
if (typeof Expo !== "undefined" && Expo.Constants) {
isExpo = Expo.Constants.appOwnership === "expo";
}
return (
<View style={{ flex: 1 }}>
{legacyMode ? (
<WebView
ref={this.getWebViewRef}
useWebKit={isExpo}
originWhitelist={["*"]}
scrollEnabled={false}
source={source}
injectedJavaScript={jsBuilder.getJavascriptSource(this.props)}
onMessage={this.onMessage}
allowFileAccess
allowUniversalAccessFromFileURLs
mixedContentMode="always"
onLoadEnd={this.props.onLoadEnd}
/>
) : (
<WebViewExternalPackage
ref={this.getWebViewRef}
useWebKit={isExpo}
originWhitelist={["*"]}
scrollEnabled={false}
source={source}
injectedJavaScript={jsBuilder.getJavascriptSource(this.props)}
onMessage={this.onMessage}
allowFileAccess
allowUniversalAccessFromFileURLs
mixedContentMode="always"
onLoadEnd={this.props.onLoadEnd}
/>
)}
</View>
);
}
}
export { ECharts };
ok solution. Not dirty at all if its works. Can you verify if it's correctly loaded on Android if you create a release version of your expo app? If everything is ok, i will implement the changes and release it in the upcoming version.
alright, sure. it can be produced with a minimal build though. seems alright on android expo.Should probably mention I tested on expo 32, and ran the example with legacyMode enabled,
using this package.json.
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject"
},
"dependencies": {
"expo": "^32.0.0",
"react": "16.5.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz",
"react-native-echarts-wrapper": "^1.4.1",
"react-native-web": "^0.11.4",
"react-native-webview": "^5.12.0"
},
"devDependencies": {
"babel-preset-expo": "^5.1.1"
},
"private": true
}
I tried @tshiamor-adft approach. It shows plain HTML instead. This occurred on both legacyMode and no-legacyMode