Apollo GraphQL+React Native在iPhone/iOS模拟器上的数据获取异常问题
我之前在React Native + Apollo开发时也碰到过类似的iOS端请求卡住的问题,结合你的场景,给你几个具体的排查和解决步骤:
1. 先检查iOS网络权限(ATS配置)
Web端没有ATS(App Transport Security)限制,但iOS默认会阻止非HTTPS的网络请求,或者未配置信任的HTTPS域名。如果你的后端是HTTP服务,或者HTTPS证书不被iOS信任,请求会被静默拦截,导致useQuery一直处于loading状态。
解决方法:
在iOS项目的Info.plist中添加ATS配置:
<key>NSAppTransportSecurity</key> <dict> <!-- 允许所有请求(仅开发环境使用,上线前要改为特定域名) --> <key>NSAllowsArbitraryLoads</key> <true/> <!-- 或者针对你的后端域名配置例外 --> <key>NSExceptionDomains</key> <dict> <key>your-backend-domain.com</key> <dict> <key>NSIncludesSubdomains</key> <true/> <key>NSAllowsArbitraryLoads</key> <true/> </dict> </dict> </dict>
2. 确认Apollo Client的URI配置是否正确
Web端用localhost:xxx没问题,但iOS模拟器的localhost指向的是模拟器自身,不是你的开发电脑。如果后端跑在本地,你需要把Apollo Client的uri改成开发电脑的局域网IP,比如:
// 之前的配置(Web端有效,RN端无效) const client = new ApolloClient({ uri: 'http://localhost:4000/graphql', cache: new InMemoryCache(), }); // 修改为电脑的局域网IP(比如192.168.1.100,根据你的实际IP调整) const client = new ApolloClient({ uri: 'http://192.168.1.100:4000/graphql', cache: new InMemoryCache(), });
你可以在终端输入ifconfig(Mac)或ipconfig(Windows)查看自己的局域网IP。
3. 加上错误捕获,看看请求到底有没有失败
你现在的代码只处理了data和loading,但没检查error。默认情况下,如果请求失败,Apollo可能不会主动抛出错误,导致你误以为还在loading。修改你的组件,加上错误处理:
function GraphListContainer() { // 添加error参数,设置errorPolicy为'all'确保捕获所有错误 const { data, loading, error } = useQuery(GET_ALL_USERS, { errorPolicy: 'all' }); // 先渲染错误信息,排查问题 if (error) { return ( <View style={styles.greetingView}> <Text style={styles.greetingText}>请求出错:{error.message}</Text> </View> ); } return ( <View style={styles.renderBlock}> {data ? ( <FlatList contentContainerStyle={listStyle.containerStyle} data={data?.getAllUsers} keyExtractor={(item) => item.id.toString()} renderItem={({ item, index }) => ( <ListRenderedTodos item={item} index={index} /> )} /> ) : loading ? ( <View style={styles.greetingView}> <Text style={styles.greetingText}>Loading...</Text> </View> ) : ( <View style={styles.greetingView}> <Text style={styles.greetingText}>Add Note...</Text> </View> )} </View> ); }
这样如果有错误(比如网络不通、查询语法错),你能直接看到具体原因。
4. 检查ApolloProvider的包裹范围
确保你的整个App都被ApolloProvider包裹,而且是在路由组件的外层。比如:
// App.js import { ApolloProvider } from '@apollo/client'; import client from './apollo-client'; import MainNavigator from './MainNavigator'; export default function App() { return ( <ApolloProvider client={client}> <MainNavigator /> </ApolloProvider> ); }
如果GraphListContainer不在ApolloProvider的范围内,useQuery根本无法发起请求,也会一直处于loading状态。
5. 排查依赖兼容性问题
虽然你已经更新了依赖,但某些版本的@apollo/client和React Native可能存在兼容性问题。比如:
- 确保
@apollo/client版本 >= 3.0(RN对3.x的支持更好) - 检查
react-native版本是否和Apollo的要求匹配
如果怀疑版本问题,可以尝试锁定已知兼容的版本:
npm install @apollo/client@3.7.17 graphql@16.6.0
先从第2、3步开始排查,这两个是最常见的原因。如果还是不行,再检查ATS配置和ApolloProvider的包裹范围。
内容的提问来源于stack exchange,提问作者Nikita Khadnevich

