react-native-navigation与Apollo的props冲突:如何同时使用二者?
嘿,这个问题我之前也碰到过!核心问题要么是你混淆了两个名称相近的导航库用法,要么是Apollo的高阶组件没正确传递navigation属性,我给你分情况理清楚:
先搞清楚你用的是哪个导航库
先去看一下你的package.json:
- 如果是
@react-navigation/native这类依赖,那你用的是官方的react-navigation; - 如果是
react-native-navigation,那是Wix开发的那个导航库,它的API和前者完全不一样。
情况1:你实际用的是react-navigation(最常见)
你遇到的报错是因为Apollo的graphql高阶组件包裹组件后,navigation属性没被正确传递下去,或者组件没被注册为导航屏幕。解决步骤:
- 确保组件被正确注册为导航屏幕
比如用createStackNavigator时,要把包裹了Apollo的组件作为屏幕注册:
import { createStackNavigator } from '@react-navigation/stack'; import { NavigationContainer } from '@react-navigation/native'; import YourApolloScreen from './YourApolloScreen'; import NewScreen from './NewScreen'; const Stack = createStackNavigator(); function App() { return ( <NavigationContainer> <Stack.Navigator> <Stack.Screen name="YourScreen" component={YourApolloScreen} /> <Stack.Screen name="NewScreen" component={NewScreen} /> </Stack.Navigator> </NavigationContainer> ); }
- 用
compose组合导航和Apollo的高阶组件
如果还是拿不到navigation,可以用withNavigation高阶组件强制注入:
import React from 'react'; import { Button, Text, View } from 'react-native'; import { graphql, compose } from '@apollo/client/react/hoc'; import { withNavigation } from '@react-navigation/native'; import YOUR_QUERY from './queries/YourQuery'; class YourScreen extends React.Component { handleGoToNewScreen = () => { const { navigate } = this.props.navigation; navigate("NewScreen"); }; render() { const { data } = this.props; const { loading, allData } = data; if (loading) return <Text>加载中...</Text>; return ( <View> <Button title="跳转到新页面" onPress={this.handleGoToNewScreen} /> {/* 渲染你的allData数据 */} </View> ); } } // 组合高阶组件,确保navigation被传递给组件 export default compose( withNavigation, graphql(YOUR_QUERY) )(YourScreen);
- 如果自定义了graphql的props,手动传递navigation
要是你在graphql里写了自定义的props函数,一定要把ownProps里的navigation手动传下去:
graphql(YOUR_QUERY, { props: ({ data, ownProps }) => ({ navigation: ownProps.navigation, // 必须加这一行 loading: data.loading, allData: data.allData }) })
情况2:你确实用的是Wix的react-native-navigation
那你之前的导航代码完全用错了!这个库根本不会给组件传递this.props.navigation,而是用componentId配合Navigation API来导航:
- 注册组件时包裹Apollo的查询
import { Navigation } from 'react-native-navigation'; import { graphql } from '@apollo/client/react/hoc'; import YourScreen from './YourScreen'; import YOUR_QUERY from './queries/YourQuery'; // 注册组件时要把Apollo的高阶组件加上 Navigation.registerComponent('YourScreen', () => graphql(YOUR_QUERY)(YourScreen));
- 使用正确的导航方式
在组件里这么写:
import React from 'react'; import { Button, Text, View } from 'react-native'; import { Navigation } from 'react-native-navigation'; class YourScreen extends React.Component { handleGoToNewScreen = () => { // Wix导航库的正确跳转方式 Navigation.push(this.props.componentId, { component: { name: 'NewScreen' // 要和你注册的新页面组件名称一致 } }); }; render() { const { data } = this.props; const { loading, allData } = data; if (loading) return <Text>加载中...</Text>; return ( <View> <Button title="跳转到新页面" onPress={this.handleGoToNewScreen} /> {/* 渲染你的allData数据 */} </View> ); } } export default YourScreen;
最后别忘了检查Apollo Provider的包裹
不管用哪个导航库,都要确保ApolloProvider包裹了整个应用的导航结构,这样所有组件都能访问Apollo的上下文:
import { ApolloProvider } from '@apollo/client'; import client from './apolloClient'; import App from './App'; import { AppRegistry } from 'react-native'; const ApolloWrappedApp = () => ( <ApolloProvider client={client}> <App /> </ApolloProvider> ); AppRegistry.registerComponent('你的应用名称', () => ApolloWrappedApp);
内容的提问来源于stack exchange,提问作者Robinia
相关产品推荐
相关产品推荐

