网络
许多移动应用需要从远程 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 或更高版本强制执行应用传输安全 (ATS)。ATS 要求任何 HTTP 连接都使用 HTTPS。如果你需要从明文 URL(以
http
开头的 URL)获取内容,你需要首先添加一个 ATS 例外。如果你提前知道需要访问哪些域,那么只为这些域添加例外会更安全;如果直到运行时才知道域,你可以完全禁用 ATS。但请注意,从 2017 年 1 月起,Apple 的 App Store 审核将要求提供禁用 ATS 的合理理由。有关更多信息,请参阅 Apple 的文档。
在 Android 上,从 API 级别 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 的安全模型与 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];
}