tomLadder / react-native-echarts-wrapper

📈Powerful React-Native ECharts Wrapper 📊

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

usage on expo as there is no android_asset folder

tshiamor-adft opened this issue · 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
}

commented

I tried @tshiamor-adft approach. It shows plain HTML instead. This occurred on both legacyMode and no-legacyMode