网络
许多移动应用程序需要从远程 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.net.cn/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.net.cn/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 级别 28 开始,默认情况下也会阻止明文流量。可以通过在应用程序清单文件中设置
android:usesCleartextTraffic
来覆盖此行为。
使用其他网络库
React Native 内置了 XMLHttpRequest API。这意味着您可以使用依赖它的第三方库(例如 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 的安全模型与 Web 上的不同,因为原生应用中没有 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 <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];
}