facebook / react-native

A framework for building native applications using React
https://reactnative.dev
MIT License
118.61k stars 24.28k forks source link

Network requests silently fail in Android since v0.63.0 #29608

Closed scobo closed 4 years ago

scobo commented 4 years ago

Description

None of the network examples work in Android since v0.63.0; iOS is unaffected. Confirmed this is still an issue in v0.63.1 and v0.63.2 (the latest as of this report). Failures are silent and simply result in no data being returned to the view.

Since this is an issue with the network APIs, this affects all libraries that rely on those APIs, e.g., Apollo.

React Native version:

System:
    OS: macOS 10.15.6
    CPU: (6) x64 Intel(R) Core(TM) i5-8500B CPU @ 3.00GHz
    Memory: 960.03 MB / 32.00 GB
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 12.18.2 - /var/folders/tb/wx5d6rj53qjdg6sr4bmb1l840000gn/T/yarn--1597082804831-0.5290956210609348/node
    Yarn: 1.22.4 - /var/folders/tb/wx5d6rj53qjdg6sr4bmb1l840000gn/T/yarn--1597082804831-0.5290956210609348/yarn
    npm: 6.14.5 - ~/.nvm/versions/node/v12.18.2/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  Managers:
    CocoaPods: 1.9.3 - /usr/local/bin/pod
  SDKs:
    iOS SDK:
      Platforms: iOS 13.6, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2
    Android SDK: Not Found
  IDEs:
    Android Studio: 4.0 AI-193.6911.18.40.6626763
    Xcode: 11.6/11E708 - /usr/bin/xcodebuild
  Languages:
    Java: 11.0.8 - /usr/bin/javac
    Python: 2.7.16 - /usr/bin/python
  npmPackages:
    @react-native-community/cli: Not Found
    react: 16.13.1 => 16.13.1 
    react-native: 0.63.2 => 0.63.2 
  npmGlobalPackages:
    *react-native*: Not Found

Steps To Reproduce

  1. Install the last known good version:
    1. npx react-native init AwesomeProject --version 0.62.2
  2. Replace the contents of App.js with one of the examples from the network docs, e.g., the Fetch Example.
  3. Run the application in iOS.
    1. npx react-native run-ios
  4. Note that the fetch example displays as intended.
  5. Run the application in Android.
    1. npx react-native run-android
  6. Note that the fetch example displays as intended.
  7. Install latest (v0.63.2 as of this report):
    1. npx react-native init AwesomeProject
  8. Replace the contents of App.js with one of the examples from the network docs, e.g., the Fetch Example.
  9. Run the application in iOS.
    1. npx react-native run-ios
  10. Note that the fetch example displays as intended.
  11. Run the application in Android.
    1. npx react-native run-android
  12. Note that a blank screen is rendered.

Expected Results

The results should be rendered as they are on iOS and as they are on versions prior to v0.63.0. At the very least, would expect to see the activity indicator and possibly an error indicating the request failed.

Snack, code example, screenshot, or link to a repository:

https://snack.expo.io/2HgnLjyI_

scobo commented 4 years ago

Fixed Snack link: https://snack.expo.io/2HgnLjyI_

scobo commented 4 years ago

With further testing, it seems v0.62.x releases do not work with iOS. Had to downgrade to v0.61.5 to get a release where the network examples work for both platforms.

safaiyeh commented 4 years ago

Hi @scobo thanks for the issue.

I checked out the example and tested it out locally. I did not see the same issue you are experiencing.

Could you provide a repo?

Screen Shot 2020-08-10 at 7 29 43 PM
scobo commented 4 years ago

This was 100% repro for us and now it’s zero. I have no idea what was wrong.

scobo commented 4 years ago

Repro again. AFACIT all I did to trigger it was cd android/ && ./gradlew clean. After that, network requests in Android fail silently 100% of the time.

scobo commented 4 years ago

100% repro with the following steps.

  1. npx react-native foobar --version 0.63.2
  2. cd foobar
  3. npx react-native run-android
  4. View demo/welcome screen.
  5. Replace App.js contents with fetch example (see Snack link above).
  6. Refresh app with R in Metro console.
  7. Blank screen. Expected: List of movies with years.
  8. Uninstall app.
  9. Ctrl+C to shut down Metro and close window.
  10. cd .. && rm -rf foobar
  11. Repeat from step 1.
scobo commented 4 years ago

Same result on iOS now.

Flipper indicates the request was successful and I can inspect the response there, but isLoading is true in the app and data is an empty array.

scobo commented 4 years ago
  1. rm -rf foobar
  2. npx react-native foobar --version 0.61.5
  3. Works.
  4. rm -rf foobar
  5. npx react-native foobar --version 0.63.2
  6. Doesn’t work.
scobo commented 4 years ago

Finally reproed on 0.61.5. It’s Flipper. Network requests are non-deterministically blocked when Flipper is running.

Edit: Nope again. Killed Flipper and still getting no data in render. This is 100% repro in 0.61.5 now, too.

scobo commented 4 years ago

AFAICT this was due to both VMs being in a bad state, although I don’t know how they got there; the lack of logs and errors made debugging impossible.

yungsters commented 4 years ago

Hey @scobo! Can you provide details on the iOS Simulator or Android Emulator (I assume this is what you meant by "VM") setup that you used to reproduce the issues? Thanks!

scobo commented 4 years ago

Hi! Your assumption is correct. I created an Android Emulator for a Pixel 3 with API 29. It worked Monday, but after logging in today the fetch example is failing to render again. Flipper indicates the GET was successful:

# HTTP request for reactnative.dev/movies.json (ID: bbd54f78-ba45-454e-ac0e-4648b4e6f11d)
## Request
HTTP GET https://reactnative.dev/movies.json
Accept-Encoding: gzip
Connection: Keep-Alive
Host: reactnative.dev
User-Agent: okhttp/3.12.1

## Response
HTTP 200 undefined
access-control-allow-origin: *
cache-control: max-age=600
cf-cache-status: DYNAMIC
cf-ray: 5c558c32085ac97d-SEA
cf-request-id: 04a955f3480000c97d38860200000001
content-encoding: gzip
content-type: application/json; charset=utf-8
date: Wed, 19 Aug 2020 17:20:51 GMT
etag: W/"5f3c38ca-1ca"
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
expires: Wed, 19 Aug 2020 17:30:51 GMT
last-modified: Tue, 18 Aug 2020 20:23:38 GMT
server: cloudflare
set-cookie: __cfduid=d2e0fa84ae6d63265349c970ae53ada5a1597857651; expires=Fri, 18-Sep-20 17:20:51 GMT; path=/; domain=.reactnative.dev; HttpOnly; SameSite=Lax
vary: Accept-Encoding
x-github-request-id: 2DAC:50DA:7B933:9598A:5F3D5F73
x-proxy-cache: MISS

{
  "title": "The Basics - Networking",
  "description": "Your app fetched this from a remote endpoint!",
  "movies": [
    { "id": "1", "title": "Star Wars", "releaseYear": "1977" },
    { "id": "2", "title": "Back to the Future", "releaseYear": "1985" },
    { "id": "3", "title": "The Matrix", "releaseYear": "1999" },
    { "id": "4", "title": "Inception", "releaseYear": "2010" },
    { "id": "5", "title": "Interstellar", "releaseYear": "2014" }
  ]
}

…but the app itself isn’t rendering the results. Again, it was working on Monday and all I’ve done is reboot.

scobo commented 4 years ago

Just tried this on an actual Android device (Pixel 4) and I’m getting the same result. And just tried in an iOS Simulator and I get a loading spinner there that never resolves.

scobo commented 4 years ago

@yungsters I think I tracked this down to the @babel/core & @babel/runtime packages and/or the metro-react-native-babel-preset.

I moved the demo apps into our monorepo, where we’re on the latest version of the Babel packages. When I did that, I also upgraded metro-react-native-babel-preset (0.63.0) since we try to keep things up-to-date. I had to downgrade both packages in order to get the networking to work again (7.8.4 for Babel, 0.59.0 for the Metro preset).

It appears something changed in either Babel or the Metro preset that causes networking requests to silently fail in React Native (both Android and iOS). You should be able to repro that locally by upgrading those packages after running npx react-native init.

scobo commented 4 years ago

Note: We also had to use "resolutions" to force "@babel/preset-env": "7.8.7" for iOS, due to this error:

error: index.ios.js: [BABEL] /index.ios.js: Could not find plugin "proposal-private-methods". Ensure there is an entry in ./available-plugins.js for it. (While processing: "/node_modules/@babel/preset-env/lib/index.js")

Otherwise Yarn picks up the latest 7.x release since it satifies semver. We still get an infinite loading spinner for iOS, but at least it renders without error.

scobo commented 4 years ago

Another update: When we build locally for Android, we have network connection and the fetch example renders as intended. When we bundle the same code for release, we get nothing in render.

scobo commented 4 years ago

No code changes since yesterday, yet today neither the demo app or the one in our monorepo have network connectivity. We’ve tried building from both macOS (two separate machines) and Ubuntu; same result in both environments. Flipper still indicates the requests are successful (and we can access the URL directly from a browser), but there’s nothing in render in the app.

scobo commented 4 years ago

Ran into a separate issue when trying to repro with an earlier version: #29781

snowloop commented 4 years ago

Hi,

I might have the same issue, did you mean that you can't do any http request or socket connection with any server from your android application ? Because that's exactly my situation, the android phone is connected but my RN android app can't connect with my server.

Have a nice day

scobo commented 4 years ago

Today’s update: Was able to install an older version of the CLI and successfully run the fetch example from the docs in React Native v0.59.10. However, the same App.js fails to render when using React Native v0.63.2. This is in a separate directory created via react-native init, not our monorepo. The issue seems to be with React Native itself.

scobo commented 4 years ago

From macOS, with both a Pixel 2 emulator and a Pixel 4 device:

  1. npx react-native init AwesomeProject
  2. cd AwesomeProject
  3. npx react-native run-android
  4. Demo page renders.
  5. Copy & paste fetch example into App.js.
  6. Refresh app via R from Metro console
  7. Empty render.

From Ubuntu 18.04, with both a Pixel 3 emulator and a Pixel 4 device:

  1. npx react-native init AwesomeProject
  2. cd AwesomeProject
  3. npx react-native run-android
  4. npx react-native start (run-android doesn’t seem to automatically launch Metro in Ubuntu.)
  5. Demo page renders.
  6. Copy & paste fetch example into App.js.
  7. Refresh app via R from Metro console
  8. Empty render.

Flipper indicates the network request was successful. Closing Flipper and refreshing the app has no affect on the outcome.

scobo commented 4 years ago

@yungsters Can you try to repro by invoking react-native via Yarn?

  1. npx react-native init AwesomeProject
  2. cd AwesomeProject
  3. yarn react-native start
  4. yarn react-native run-android

We repro’d on a “clean” machine which was able to run the fetch example successfully via npx. Subsequently invoking yarn react-native start seemed to “poison“ the machine and network requests would no longer work (on emulators or devices), even after switching back to npx react-native.

scobo commented 4 years ago

More info: If we invoke Metro via yarn in our monorepo, it seems to “poison” the Metro cache. Running yarn react-native --reset-cache in the monorepo has no effect. We have to create a demo app with the same package name to clean it, e.g., npx react-native init <ourproject> && cd <ourproject> && npx react-native start --reset-cache, then the app works again. It appears Metro caches based on the project name, is that accurate?

Also, while this workaround works for the development builds, the release builds still have no network connectivity, e.g., npx react-native run-android works but not npx react-native run-android --variant=release.

Edit: Running a release build also appears to “poison” the Metro cache.

scobo commented 4 years ago

Closing this issue since we’ve verified that un-poisoning the Metro cache by running a demo app with the same package name allows us to run debug and release builds of the demo app successfully.

It’s still not clear, however, what the issue is when running in our monorepo or how or why running the app in our monorepo poisons the Metro cache for all React Native apps. Since Flipper indicates the network requests are successful, we’re at a loss on how to debug the issue. Any help would be appreciated.

higoramp commented 3 years ago

I'm having a similar problem trying to execute the examples from the network docs. If I enable the network inspect, everything works ok, but on release, the fetch hangs and don't even give me an error. I can reproduce the error following the steps:

  1. npx react-native init AwesomeProject
  2. Add a Button with the fetch call inside onPress event

Tested using react-native 0.63.4 and 0.62.2

danmaas commented 3 years ago

Not sure if this is relevant, but I hit an issue a few weeks ago where connections to IPv6 addresses would fail silently in the OkHTTP library on one device I had. Telling OkHTTP to prioritize IPv4 over IPv6 fixed it.

cristianoccazinsp commented 3 years ago

@danmaas how do you "tell OkHTTP" to prioritize IPv4 from react native?

danmaas commented 3 years ago

@cristianoccazinsp Here is a Gist with the relevant code excerpt:

https://gist.github.com/danmaas/c60af5fed9f55d2bc616ce302696540d

This overrides the default OkHTTP client factory with a shim that intercepts DNS resolutions and sorts the result list to return IPv4 addresses before IPv6 addresses.