網路功能
許多行動應用程式需要從遠端 URL 載入資源。您可能想要向 REST API 發出 POST 請求,或者您可能需要從另一個伺服器擷取一塊靜態內容。
使用 Fetch
React Native 提供了 Fetch API 以滿足您的網路需求。如果您以前使用過 XMLHttpRequest
或其他網路 API,您會覺得 Fetch 很熟悉。您可以參考 MDN 關於 使用 Fetch 的指南以獲取更多資訊。
發出請求
為了從任意 URL 擷取內容,您可以將 URL 傳遞給 fetch
fetch('https://mywebsite.com/mydata.json');
Fetch 也接受一個可選的第二個參數,允許您自訂 HTTP 請求。您可能想要指定額外的標頭,或發出 POST 請求
fetch('https://mywebsite.com/endpoint/', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
firstParam: 'yourValue',
secondParam: 'yourOtherValue',
}),
});
請查看 Fetch Request 文件 以取得完整的屬性列表。
處理回應
以上範例示範了如何發出請求。在許多情況下,您會想要對回應執行一些操作。
網路功能本質上是非同步操作。Fetch 方法將返回一個 Promise,使其能夠直接編寫以非同步方式運作的程式碼
const getMoviesFromApi = () => {
return fetch('https://reactnative.dev.org.tw/movies.json')
.then(response => response.json())
.then(json => {
return json.movies;
})
.catch(error => {
console.error(error);
});
};
您也可以在 React Native 應用程式中使用 async
/ await
語法
const getMoviesFromApiAsync = async () => {
try {
const response = await fetch(
'https://reactnative.dev.org.tw/movies.json',
);
const json = await response.json();
return json.movies;
} catch (error) {
console.error(error);
}
};
別忘了捕獲 fetch
可能拋出的任何錯誤,否則它們將被靜默丟棄。
- TypeScript
- JavaScript
預設情況下,iOS 9.0 或更高版本會強制執行 App Transport Security (ATS)。ATS 要求任何 HTTP 連線都必須使用 HTTPS。如果您需要從明文 URL (以
http
開頭的 URL) 擷取內容,您首先需要新增 ATS 例外。如果您提前知道您需要存取哪些網域,則僅為這些網域新增例外更安全;如果網域在執行階段之前未知,您可以完全停用 ATS。但請注意,從 2017 年 1 月起,Apple 的 App Store 審查將要求對停用 ATS 提出合理的理由。請參閱 Apple 的文件 以取得更多資訊。
在 Android 上,從 API Level 28 開始,預設情況下也會封鎖明文流量。可以透過在應用程式資訊清單檔案中設定
android:usesCleartextTraffic
來覆寫此行為。
使用其他網路程式庫
XMLHttpRequest API 已內建於 React Native 中。這表示您可以使用依賴它的第三方程式庫,例如 frisbee 或 axios,或者如果您願意,也可以直接使用 XMLHttpRequest API。
const request = new XMLHttpRequest();
request.onreadystatechange = e => {
if (request.readyState !== 4) {
return;
}
if (request.status === 200) {
console.log('success', request.responseText);
} else {
console.warn('error');
}
};
request.open('GET', 'https://mywebsite.com/endpoint/');
request.send();
XMLHttpRequest 的安全性模型與網頁上不同,因為在原生應用程式中沒有 CORS 的概念。
WebSocket 支援
React Native 也支援 WebSockets,這是一種透過單一 TCP 連線提供全雙工通訊通道的協定。
const ws = new WebSocket('ws://host.com/path');
ws.onopen = () => {
// connection opened
ws.send('something'); // send a message
};
ws.onmessage = e => {
// a message was received
console.log(e.data);
};
ws.onerror = e => {
// an error occurred
console.log(e.message);
};
ws.onclose = e => {
// connection closed
console.log(e.code, e.reason);
};
使用 fetch
和 Cookie 基礎驗證的已知問題
以下選項目前無法與 fetch
搭配使用
redirect:manual
credentials:omit
- 在 Android 上具有相同名稱的標頭將導致僅顯示最新的標頭。可以在這裡找到臨時解決方案:https://github.com/facebook/react-native/issues/18837#issuecomment-398779994。
- Cookie 基礎驗證目前不穩定。您可以在這裡查看提出的一些問題:https://github.com/facebook/react-native/issues/23185
- 至少在 iOS 上,當透過
302
重新導向時,如果存在Set-Cookie
標頭,則 Cookie 無法正確設定。由於重新導向無法手動處理,如果重新導向是由過期的會話導致,則可能會導致無限請求的情況發生。
在 iOS 上設定 NSURLSession
對於某些應用程式,可能適合為在 iOS 上執行的 React Native 應用程式中用於網路請求的底層 NSURLSession
提供自訂 NSURLSessionConfiguration
。例如,可能需要為來自應用程式的所有網路請求設定自訂使用者代理字串,或為 NSURLSession
提供暫時性的 NSURLSessionConfiguration
。函數 RCTSetCustomNSURLSessionConfigurationProvider
允許進行此類自訂。請記住在將呼叫 RCTSetCustomNSURLSessionConfigurationProvider
的檔案中新增以下 import
#import <React/RCTHTTPRequestHandler.h>
RCTSetCustomNSURLSessionConfigurationProvider
應該在應用程式生命週期的早期呼叫,以便在 React 需要時隨時可用,例如
-(void)application:(__unused UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// set RCTSetCustomNSURLSessionConfigurationProvider
RCTSetCustomNSURLSessionConfigurationProvider(^NSURLSessionConfiguration *{
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
// configure the session
return configuration;
});
// set up React
_bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
}