React Native ~ Networking - rohit120582sharma/Documentation GitHub Wiki
Many mobile apps need to load resources from a remote URL. You may want to make a POST request to a REST API, or you may simply need to fetch a chunk of static content from another server.
React Native is a complex platform in terms of composition of different patterns, libraries and architectural solutions. Network layer is only a one of many interesting topics that powers the platform.
React Native ships with three network APIs available by default: fetch
, XMLHttpRequest
and WebSocket
.
Neither of these APIs is a part of ECMAScript standard which means that JavaScript doesn’t have any standardised ways of transmitting packages over the wire.
Therefore, if we want to perform network requests from JavaScript, we need to extend its runtime by a custom functionality implemented by the underlying host platform (which is React Native in our case).
So it turns out that React Native should supply/expose fetch
, XMLHttpRequest
and WebSocket
APIs to JS runtime.
XMLHttpRequest (XHR) is an object that is used to interact with remote resources.
In React Native, XMLHttpRequest
consists of two parts: front-end and back-end. The front-end part is something that you can interact with in JavaScript. It is capable of sending appropriate request data to the XHR back-end which is responsible for processing network request and using underlying mobile platform.
The back-end part of XMLHttpRequest
is called Networking.
It is an abstraction on top of iOS and Android operating systems that provides a unified API layer that front-end can work with. Implementation of this layer is different for each platform. While on iOS Networking
module takes advantage of built-in URLSession, Android version works on top of third-party OkHTTP library that supplies a certain abstraction for low-level Java networking API.
Therefore, once developer make a request, it goes through React Native’s Networking
module and underlying operating system right to the requested resource.
Fetch
is a modern concept equivalent to XMLHttpRequest
.
In React Native (in order to not to re-implement a new API for both platforms), it uses GitHub’s whatwg-fetch polyfill that relies on XMLHttpRequest
implementation, so it implicitly uses React Native’s Networking
module under the hood.
The whatwg-fetch
module is a polyfill that implements a subset of the standard Fetch specification
, enough to make fetch a viable replacement for most uses of XMLHttpRequest in traditional web applications.
Importing will automatically polyfill window.fetch
and related APIs:
import 'whatwg-fetch';
-
The Promise returned from
fetch()
won't reject on HTTP error status even if the response is an HTTP 404 or 500. Instead, it will resolve normally, and it will only reject on network failure or if anything prevented the request from completing. -
fetch is a very explicit API, you don’t get anything unless you ask for it. In order to sending POST request to server; the JSON must be converted to a string and the ‘Content-Type’ header must indicate that the payload is JSON, otherwise the server will treat it as a string.
fetch('/user', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ firstName: 'Fred', lastName: 'Flintstone' }) });
-
For CORS requests, use
credentials: 'include'
to allow sending credentials to other domains:fetch('https://example.com:1234/users', { credentials: 'include' })
WebSocket is a communications protocol, providing full-duplex communication channels over a single TCP connection.
You might already use WebSockets for developing your React Native applications. Every time you start an app in development mode, it creates a WebSocket connection between packager and the app itself, so every time you edit your JS files (or other static assets), it sends a patch signal to the app so it can react to the changes.
In order to fetch content from an arbitrary URL, just pass the URL to fetch:
fetch('https://mywebsite.com/mydata.json');
Fetch also takes an optional second argument that allows you to customize the HTTP request. You may want to specify additional headers, or make a POST request:
fetch('https://mywebsite.com/endpoint/', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
firstParam: 'yourValue',
secondParam: 'yourOtherValue',
}),
});
Networking is an inherently asynchronous operation. Fetch methods will return a Promise that makes it straightforward to write code that works in an asynchronous manner:
function getMoviesFromApiAsync() {
return fetch('https://facebook.github.io/react-native/movies.json')
.then((response) => response.json())
.then((responseJson) => {
return responseJson.movies;
})
.catch((error) => {
console.error(error);
});
}
In order to submit an iOS app to Apple's App Store, and to keep it as secure as possible, we have to define the NSAppTransportSecurity
inside Info.plist file, in which we can define a list of all the domains the app can make HTTP request to.
By default, iOS is just going to block the requests to unspecified domains. If you need to fetch from a cleartext URL (one that begins with http) you will first need to add an App Transport Security exception.
I know that just setting NSAllowsArbitraryLoads
key to true
enables your app to make requests for any domain, but since it decreases security, it's not a good option (and you'll have to justify it to Apple during the app review process).
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>demo.bolty.blue</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>TLSv1.1</string>
</dict>
</dict>
</dict>
If you ever developed a mobile application using React Native, you might notice that it exposes a great way of debugging JavaScript code — Chrome Developer Tools (CDT).
Due to implementation specifics, CDT is not capable of handling network requests. If we consider web platform, XHR
, fetch
and WebSocket
APIs are backed by the browser itself which gives it an advantage of having spies that makes it possible to trace network requests. However, React Native doesn’t use Chrome to make networking requests (all network requests goes through the Networking
module no matter what), so it can’t trace them.
React Native ships with two interceptors XHRInterceptor
for XMLHttpRequest & fetch requests and WebSocketInterceptor
for WebSockets accordingly. Interceptors can be spied to trace the remote requests where the Reactotron
comes into the pircture.
Reactotron is a swiss knife for React(+Native) development that provides lots of helpful functionality like debugging network requests, redux actions, sagas and much much more.