I've just encountered this when making a project that shares code between React Native v0.59.5
and React Native Web v0.11.2
. fetch
is a global API available in both environments (but admittedly may need polyfilling for the latter if you're targeting very old browsers). Interestingly, React Native's implementation of fetch is identical to the kind that you'd polyfill for web browsers (whatwg-fetch
), so their underlying XmlHttpRequest implementation is probably where things differ.
fetch("some/relative/resource.txt")
.then((response) => { console.log("Responded!"); })
.catch(console.error);
// On React Native, logs the error "Network request failed".
// On React Native Web, logs "Responded!"
As I was connecting to localhost over the http://
protocol, I double-checked that my App Transport security was set up correctly (it was).
In the case of React Native, no corresponding request is even shown in the network debugger, so I suspected a security violation. Then I realised that it's quite obvious: on React Native Web, the app is always hosted on the web, so it's natural that fetch()
requests are made relative to that domain. But React Native apps are not hosted on a domain.
It looks like React Native's implementation passes the URL onto RCTNetworking.sendRequest(), and then ultimately on to RCTNetworking.mm
here, at least for iOS. It ends up as a [NSMutableURLRequest requestWithURL:URL]
using an NSURL formed from the dictionary via [RCTConvert NSURL:query[@"url"]]
. The implementation of RCTConvert here shows that the NSURL is initialised using the [NSURL URLWithString:path]
method with no relativeToURL
path, so the URL is relative to nothing (and may well return nil
)! So it's no wonder that it fails. It's also clear from the implementation that there's no way in React Native to globally declare a URL base to base such URLs relative to.
There's definitely potential for a Pull Request in here to improve parity between React Native and React Native Web. But until then, something along the lines of phillipsh's solution, wherein you explicitly detail the host domain, will have to do..!
Relevant reading