highcharts / highcharts-react-native

Other
103 stars 79 forks source link

Not rendering in iOS release mode #104

Open horstleung opened 4 years ago

horstleung commented 4 years ago

getting error:

Failed to fetch scripts or layout. File 'file:///{USER_PATH}/Library/Developer/CoreSimulator/Devices/D53BDBF8-65D5-4AC5-9436-39A94EF1CE60/data/Containers/Data/Application/879BAB8F-D419-4908-8317-01B556F7BCFA/Library/Caches/ExponentAsset-ffceb4b4585b380fc666d3882abee7e5.html' could not be read.
horstleung commented 4 years ago

Hotfix

Modifiy setLayout in HighchartsReactNative.js

setLayout = async () => {
        const indexHtml = Asset.fromModule(require('../highcharts-layout/index.html'))
        this.setState({
            layoutHTML: await FileSystem.readAsStringAsync(indexHtml.uri)
        })
    }

@Denyllon I don't understand the original flow (downloading a local file to cache folder and read that).

Denyllon commented 4 years ago

@fattomhk We need to load the local index.html file and register it as an asset, read it as a string, and then pass as the html value for Webview here: https://github.com/highcharts/highcharts-react-native/blob/64f6d610555a92270667051bebff432d48d31a7b/dist/src/HighchartsReactNative.js#L209-L213

Could you provide us with the minimal project where the problem occurs?

horstleung commented 4 years ago

Sorry for not setting up a repo as I made this in work.

Here is the minimal project.(setup ios only.) https://drive.google.com/file/d/1L1L9iJITAPfWbu5h4i5fYtJYTTVeIxMZ/view?usp=sharing

You can run yarn ios to show the chart. But if can't see any if you run it through XCode (as I set the target to release mode).

there is a patch in patches folder for my hotfix. you can apply it by npx patch-package

Denyllon commented 4 years ago

@fattomhk Thank you. We will take a look on it as soon as possible.

vinasgo commented 4 years ago

I have the same problem. In debug mode it works perfectly, but in realease mode I get this error message on Xcode. "Failed to fetch scripts or layout. File 'file:///Users/Vinas/Library/Developer/CoreSimulator/Devices/C375A33E-EFA3-4983-B644-2E66FFD7C5BA/data/Containers/Data/Application/868BF4A0-E28C-4C4F-9485-95D94CA0BB3C/Library/Caches/ExponentAsset-ffceb4b4585b380fc666d3882abee7e5.html' could not be read."

jenniferburch commented 4 years ago

Is there any update on this ticket? I'm not getting any charts on a real iOS device. (in the emulator it's fine)

vinasgo commented 4 years ago

Hotfix

Modifiy setLayout in HighchartsReactNative.js

setLayout = async () => {
        const indexHtml = Asset.fromModule(require('../highcharts-layout/index.html'))
        this.setState({
            layoutHTML: await FileSystem.readAsStringAsync(indexHtml.uri)
        })
    }

@Denyllon I don't understand the original flow (downloading a local file to cache folder and read that).

It works!

horstleung commented 4 years ago

@jenniferburch If you are rushing, you might apply my hotfix yourself or apply the patch in my google drive's zip by copying patches folder to your project and run npx patch-package.

I don't understand the original flow otherwise I would create a pull request. So, if you are not rushing, you better wait for the official fix.

aditya1711 commented 4 years ago

Hotfix

Modifiy setLayout in HighchartsReactNative.js

setLayout = async () => {
        const indexHtml = Asset.fromModule(require('../highcharts-layout/index.html'))
        this.setState({
            layoutHTML: await FileSystem.readAsStringAsync(indexHtml.uri)
        })
    }

@Denyllon I don't understand the original flow (downloading a local file to cache folder and read that).

This doesn't work for me. With a different but similar error message.

Failed to fetch scripts or layout. File 'file:///{USER_PATH}/Library/Developer/CoreSimulator/Devices/00C9E684-010E-45E1-AE2E-48FF90A469B9/data/Containers/Data/Application/D50BE37B-07F2-4800-B853-18066208FCA2/Library/Caches/ExponentAsset-854c52eea1c8666bdc81b6d4f0a46808.hcscript' could not be read.

horstleung commented 4 years ago

Hotfix

Modifiy setLayout in HighchartsReactNative.js

setLayout = async () => {
        const indexHtml = Asset.fromModule(require('../highcharts-layout/index.html'))
        this.setState({
            layoutHTML: await FileSystem.readAsStringAsync(indexHtml.uri)
        })
    }

@Denyllon I don't understand the original flow (downloading a local file to cache folder and read that).

This doesn't work for me. With a different but similar error message.

Failed to fetch scripts or layout. File 'file:///{USER_PATH}/Library/Developer/CoreSimulator/Devices/00C9E684-010E-45E1-AE2E-48FF90A469B9/data/Containers/Data/Application/D50BE37B-07F2-4800-B853-18066208FCA2/Library/Caches/ExponentAsset-854c52eea1c8666bdc81b6d4f0a46808.hcscript' could not be read.

My hotfix is solving the html asset loading problem only.

I think that is the same problem with the html one.

a guess, haven't tried:

addScript = async (name, isModule, useCDN) => {
        if(useCDN) {
            const response = await fetch(
                httpProto + cdnPath + (isModule ? 'modules/' : '') + name + '.js'
            ).catch((error) => {
                throw error
            })
            stringifiedScripts[name] = await response.text()
        } else {
            const script = Asset.fromModule(
                isModule &&
                name !== 'highcharts-more' &&
                name !== 'highcharts-3d' ?
                HighchartsModules.modules[name] : HighchartsModules[name]
            )
            stringifiedScripts[name] = await FileSystem.readAsStringAsync(script.uri) 
// origin: await this.getAssetAsString(script)
        }
    }

Btw, maybe setting useCDN would get through the script loading part.

Denyllon commented 4 years ago

@fattomhk Apologize for that takes so long, though unfortunately I still haven't had chance to run your project due to general overload of work this week (many things to close in other projects before going on vacation). I will get back to this issue right after back to the office (29th of September).

Kind regards, and than you for your patience!

horstleung commented 4 years ago

nvm, enjoy your holiday.

zjhiphop commented 4 years ago

I also have this issue, and can not resolve with the above solution.

jenniferburch commented 4 years ago

The patch did work in my project if running from Xcode but is still broken if running through the command line, react-native run-ios, (still unable to fetch the script) but as a stop gap (and this is a SUPER hack), in src/HighChartsReactNative.js

  1. comment out the contents of setLayout
  2. in the render() method, change the WebView source to be: source = { {
    html: COPY PASTE THE CONTENTS OF ../highcharts-layout/index.html } }

You will also need to set useCDN={true} when you render

horstleung commented 4 years ago

The patch did work in my project if running from Xcode but is still broken if running through the command line, react-native run-ios, (still unable to fetch the script) but as a stop gap (and this is a SUPER hack), in src/HighChartsReactNative.js

  1. comment out the contents of setLayout
  2. in the render() method, change the WebView source to be: source = { { html: COPY PASTE THE CONTENTS OF ../highcharts-layout/index.html } }

You will also need to set useCDN={true} when you render

What error did you get after applying the patch and set useCDN to true?

jenniferburch commented 4 years ago

@fattomhk error in debugger: ExceptionsManager.js:179 Failed to fetch scripts or layout. Unsupported URI scheme for 'http://localhost:8081/assets/node_modules/@highcharts/highcharts-react-native/highcharts-layout/index.html?platform=ios&hash=ffceb4b4585b380fc666d3882abee7e5'

Denyllon commented 4 years ago

Hello @fattomhk @jenniferburch @zjhiphop, Sorry for that it takes so long, but this problem is very complex, and unfortunately there is no any quick/simple solution to get rid of it, because the FileSystem and Asset objects from react-native-unimodules have significant differences in a process of how they work on different environments (Simulators, real devices, operating systems).

For example, when using the Asset.asyncDownload() on iOS Simulator, all files are downloaded into the FileSystem.cacheDirectory and because of that fact we are able to avoid downloading them multiple times one by one, by checking whether are they already downloaded in the mentioned directory. In case of running the app on a real device, files are not available there though, and they have completely different path structure.

Furthermore, while I've tried to always use the path from downloaded asset localUri property, then it breeds further problems. When having (let's say) about 20 charts with multiple modules (funnel, range, bullet etc.) in one App, then, I guess, it generates too many file read requests, and then the error is thrown from FileSystem. For some reason it is not able to read the file... but only on Simulators though.

As you can see, for now, we are not able to give you any perfect and universal solution, which could be applied to resolve all of reported issues. We definitely need to discuss the architecture of managing files in this wrapper, and find some compromise. That means, it can takes a while.

Kind regards!

wzhang2 commented 4 years ago

is this only happening on some versions of react native? we just updated to rn63.3, and now we are seeing this issue, but was fine on 61.2 with react-native-unimodules on 0.7.0

Denyllon commented 4 years ago

I guess that's what it comes to. Or, the react-native-unimodules works differently with different React Native versions. The problem is very complex, most probably nested somewhere in the dependent packages, and it's hard to find out what causing the issue.

AnthonyTailer commented 4 years ago

I'm getting the same behavior here. After upgrade my project from RN 0.61.5 to 0.63.3 and using Xcode 12. Works on Debug but not in Release mode.

I have tried the suggestions above. The one that worked was the "guess" comment by @fattomhk.

So I applied this patch with patch-package and set useCDN as false on HC component options:

diff --git a/node_modules/@highcharts/highcharts-react-native/src/HighchartsReactNative.js b/node_modules/@highcharts/highcharts-react-native/src/HighchartsReactNative.js
index fabd55a..c284c26 100755
--- a/node_modules/@highcharts/highcharts-react-native/src/HighchartsReactNative.js
+++ b/node_modules/@highcharts/highcharts-react-native/src/HighchartsReactNative.js
@@ -74,15 +74,14 @@ export default class HighchartsReactNative extends React.PureComponent {
                 name !== 'highcharts-3d' ?
                 HighchartsModules.modules[name] : HighchartsModules[name]
             )
-            stringifiedScripts[name] = await this.getAssetAsString(script)
+            stringifiedScripts[name] = await FileSystem.readAsStringAsync(script.uri)
         }
     }

     setLayout = async () => {
         const indexHtml = Asset.fromModule(require('../highcharts-layout/index.html'))
-
         this.setState({
-            layoutHTML: await this.getAssetAsString(indexHtml)
+            layoutHTML: await FileSystem.readAsStringAsync(indexHtml.uri)
         })
     }

My package.json:

{
  "@highcharts/highcharts-react-native": "^3.1.2",
  "react": "16.13.1",
  "react-native": "0.63.3",
  "react-native-unimodules": "^0.11.0",
  "react-native-webview": "^10.9.2",
}
zjhiphop commented 3 years ago

@AnthonyTailer @fattomhk I tried your solution in develop mode, it reported "Failed to fetch scripts or layout. Unsupported URI scheme for '....' '".

Is there any solution could support both develop and release mode?

zjhiphop commented 3 years ago

Minimal code change to fix the issue and support for both dev and release mode. Just update getAssetAsString to following will done:

 getAssetAsString = async (asset) => {
        if (!__DEV__) {
            return await FileSystem.readAsStringAsync(asset.uri);
        }

        const downloadedModules = await FileSystem.readDirectoryAsync(FileSystem.cacheDirectory)
        let fileName = 'ExponentAsset-' + asset.hash + '.' + asset.type

        if (!downloadedModules.includes(fileName)) {
            await asset.downloadAsync()
        }

        return await FileSystem.readAsStringAsync(FileSystem.cacheDirectory + fileName)
    }
miansohaibkhalid commented 3 years ago

@AnthonyTailer @fattomhk I tried your solution in develop mode, it reported "Failed to fetch scripts or layout. Unsupported URI scheme for '....' '".

Is there any solution could support both develop and release mode?

You should try this one. It's working on both modes: https://github.com/highcharts/highcharts-react-native/issues/104#issuecomment-696327683

horstleung commented 3 years ago

Minimal code change to fix the issue and support for both dev and release mode. Just update getAssetAsString to following will done:

 getAssetAsString = async (asset) => {
        if (!__DEV__) {
            return await FileSystem.readAsStringAsync(asset.uri);
        }

        const downloadedModules = await FileSystem.readDirectoryAsync(FileSystem.cacheDirectory)
        let fileName = 'ExponentAsset-' + asset.hash + '.' + asset.type

        if (!downloadedModules.includes(fileName)) {
            await asset.downloadAsync()
        }

        return await FileSystem.readAsStringAsync(FileSystem.cacheDirectory + fileName)
    }

I faced the problem and tried this fix this week. Thanks for saving my hours.

hardiksonagrav commented 3 years ago

I'm getting the same behavior here. After upgrade my project from RN 0.61.5 to 0.63.3 and using Xcode 12. Works on Debug but not in Release mode.

I have tried the suggestions above. The one that worked was the "guess" comment by @fattomhk.

So I applied this patch with patch-package and set useCDN as false on HC component options:

diff --git a/node_modules/@highcharts/highcharts-react-native/src/HighchartsReactNative.js b/node_modules/@highcharts/highcharts-react-native/src/HighchartsReactNative.js
index fabd55a..c284c26 100755
--- a/node_modules/@highcharts/highcharts-react-native/src/HighchartsReactNative.js
+++ b/node_modules/@highcharts/highcharts-react-native/src/HighchartsReactNative.js
@@ -74,15 +74,14 @@ export default class HighchartsReactNative extends React.PureComponent {
                 name !== 'highcharts-3d' ?
                 HighchartsModules.modules[name] : HighchartsModules[name]
             )
-            stringifiedScripts[name] = await this.getAssetAsString(script)
+            stringifiedScripts[name] = await FileSystem.readAsStringAsync(script.uri)
         }
     }

     setLayout = async () => {
         const indexHtml = Asset.fromModule(require('../highcharts-layout/index.html'))
-
         this.setState({
-            layoutHTML: await this.getAssetAsString(indexHtml)
+            layoutHTML: await FileSystem.readAsStringAsync(indexHtml.uri)
         })
     }

My package.json:

{
  "@highcharts/highcharts-react-native": "^3.1.2",
  "react": "16.13.1",
  "react-native": "0.63.3",
  "react-native-unimodules": "^0.11.0",
  "react-native-webview": "^10.9.2",
}

Working fine.

utsavGridKey commented 5 months ago

Hey Falas, I have tried all the above solution but at the end i have this error and this the issue with highchart react native

Failed to fetch scripts or layout. Calling the 'readAsStringAsync' function has failed → Caused by: File '/~assets/ffceb4b4585b380fc666d3882abee7e5' is not readable