expo / expo

An open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.
https://docs.expo.dev
MIT License
34.05k stars 5.45k forks source link

XMLHttpRequestUpload events not firing in Expo Go 49+ #28269

Open cshfang opened 6 months ago

cshfang commented 6 months ago

Minimal reproducible example

https://github.com/cshfang/xhr-issue

What platform(s) does this occur on?

iOS

Did you reproduce this issue in a development build?

No (tested in Expo Go)

Summary

XMLHttpRequestUpload events appear to be not firing in Expo Go 49+

Related discussion found here: https://github.com/expo/expo/discussions/27448

Example code of xhr events not firing:

xhr.upload.addEventListener('progress', event => {
  console.log('Event: Upload progress', event); // does not fire during upload
});
xhr.upload.onprogress = event => {
  console.log('Upload progress', event); // does not fire during upload
};
Platform XMLHttpRequestUpload events firing
React Native 0.71
React Native 0.73
Expo Go SDK 48
Expo Go SDK 50
Expo Dev Build SDK 50

Environment

Run within xhr-latest (app presenting with issue) directory

  expo-env-info 1.2.0 environment info:
    System:
      OS: macOS 14.4
      Shell: 5.9 - /bin/zsh
    Binaries:
      Node: 18.18.0 - ~/.nvm/versions/node/v18.18.0/bin/node
      Yarn: 1.22.19 - ~/.nvm/versions/node/v18.18.0/bin/yarn
      npm: 9.8.1 - ~/.nvm/versions/node/v18.18.0/bin/npm
    Managers:
      CocoaPods: 1.13.0 - /Users/chrfang/.rbenv/shims/pod
    SDKs:
      iOS SDK:
        Platforms: DriverKit 23.0, iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0
      Android SDK:
        API Levels: 26, 28, 30, 31, 32, 33, 34
        Build Tools: 28.0.3, 30.0.2, 30.0.3, 31.0.0, 33.0.0, 33.0.1, 34.0.0, 34.0.0
        System Images: android-24 | Google APIs ARM 64 v8a, android-26 | Google APIs ARM 64 v8a, android-32 | Google APIs ARM 64 v8a, android-33 | Google APIs ARM 64 v8a, android-33 | Google Play ARM 64 v8a, android-34 | Google Play ARM 64 v8a
    IDEs:
      Android Studio: 2022.3 AI-223.8836.35.2231.10671973
      Xcode: 15.0/15A240d - /usr/bin/xcodebuild
    npmPackages:
      expo: ~50.0.14 => 50.0.17 
      react: 18.2.0 => 18.2.0 
      react-native: 0.73.6 => 0.73.6 
    npmGlobalPackages:
      eas-cli: 5.9.1
    Expo Workflow: managed

Expo Doctor Diagnostics

Run within xhr-latest (app presenting with issue) directory

✔ Check Expo config for common issues
✔ Check package.json for common issues
✔ Check native tooling versions
✔ Check dependencies for packages that should not be installed directly
✔ Check for common project setup issues
✔ Check npm/ yarn versions
✔ Check for issues with metro config
✔ Check Expo config (app.json/ app.config.js) schema
✔ Check that native modules do not use incompatible support packages
✔ Check for legacy global CLI installed locally
✔ Check that native modules use compatible support package versions for installed Expo SDK
✔ Check that packages match versions required by installed Expo SDK

Didn't find any issues with the project!
ChristopherGabba commented 6 months ago

Referencing other issues:

I'm seeing this as well in an Expo Development build.

ChristopherGabba commented 4 months ago

@byCedric Good morning, any update on this? For slow internet connection, it is 10x user experience to be able to show progress updates on upload. With this not functioning, the "upload bar" in my app just sticks until it is complete. Getting the onProgress callbacks solves this issue.

faarda commented 3 months ago

Did you find a work around for this @cshfang ?

brentvatne commented 3 months ago

@ChristopherGabba - as far as i know this only impacts expo go, as reported here, so it should not have any impact on your users. are you experiencing something different?

expo-bot commented 3 months ago

Thank you for filing this issue! This comment acknowledges we believe this may be a bug and there’s enough information to investigate it. However, we can’t promise any sort of timeline for resolution. We prioritize issues based on severity, breadth of impact, and alignment with our roadmap. If you’d like to help move it more quickly, you can continue to investigate it more deeply and/or you can open a pull request that fixes the cause.

brentvatne commented 3 months ago

this seems to coincide with the release of network debugging: https://blog.expo.dev/expo-sdk-49-c6d398cdf740

i was able to reproduce it in expo go in a new app by copying @cshfang's app code over to a new project. outside of expo go, it works as expected (eg: via npx expo run:ios)

import React from 'react';
import {Button, StyleSheet, View} from 'react-native';

const url = 'http://127.0.0.1:3000';
export default function App() {
  const upload = () => {
    const xhr = new XMLHttpRequest();
    xhr.open('POST', url);
    xhr.upload.addEventListener('progress', event => {
      console.log('Event: Upload progress', event);
    });
    xhr.upload.onprogress = event => {
      console.log('Upload progress', event);
    };
    xhr.onprogress = event => {
      console.log('Progress', event);
    };
    xhr.onload = event => {
      console.log('Completed', event);
    };
    xhr.send('just a string');
  };
  return (
    <View style={styles.container}>
      <Button title="Upload" onPress={upload} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

//  LOG  Event: Upload progress {"isTrusted": false, "lengthComputable": true, "loaded": 13, "total": 13}
//  LOG  Upload progress {"isTrusted": false, "lengthComputable": true, "loaded": 13, "total": 13}
//  LOG  Progress {"isTrusted": false, "lengthComputable": false, "loaded": 13, "total": -1}
//  LOG  Completed {"isTrusted": false}

and then running his provided server code:

const http = require('http')

const server = http.createServer(function(request, response) {
  if (request.method == 'POST') {
    var body = ''
    request.on('data', function(data) {
      body += data
    })
    request.on('end', function() {
      console.log('Body: ' + body)
      response.writeHead(200, {'Content-Type': 'text/html'})
      response.end('post received')
    })
  }
})

const port = 3000
const host = '127.0.0.1'
server.listen(port, host)
console.log(`Listening at http://${host}:${port}`)
ChristopherGabba commented 3 months ago

@brentvatne @Kudo I am experiencing this issue in my production app on Expo 51 as well (on iOS)so it's not just Expo Go. I'm unable to get progress feedback on uploads.

brentvatne commented 3 months ago

@ChristopherGabba - we can only help on reports where there is a minimal reproducible example. we are unable to reproduce this outside of expo go. please share a minimal reproducible example in a new issue if you believe that you have found a bug - this issue is about expo go

ChristopherGabba commented 3 months ago

@brentvatne I apologize, I'll work on it. @cshfang posted this issue on behalf of the AWS team who were troubleshooting my issue on AWS: https://github.com/aws-amplify/amplify-js/issues/13221 . Essentially using the AWS uploadData function, all onProgress callbacks produce no feedback. They dug into the underlying XMLHttpRequest and reported this issue. But the same issue exists on an expo development build and an expo production build for iOS.

brentvatne commented 3 months ago

@ChristopherGabba - if you can reproduce it without using amplify that would be great! the code provided by the OP in this thread works as expected in a release build

ChristopherGabba commented 2 months ago

@brentvatne Super strange. The upload progress is actually working on a production TestFlight build, but not on the Expo Dev Build -- just using the basic amplify uploadData (https://docs.amplify.aws/react-native/build-a-backend/storage/upload-files/) function. I coded it into the app, and it wasn't working on Dev and as soon as I downloaded the Testflight build it works awesome -- still can't get any in the development build though.

Regardless, I have not been able to reproduce it without the basic Amplify library, but just providing an update.