React/React-Native中React-navigation如何仅为部分页面包裹Context
报错原因
react-navigation 的导航器(比如Stack.Navigator)要求直接子元素必须是Stack.Screen组件,不能直接插入Provider等其他组件,所以你直接在导航器内部包裹Provider会触发报错。
实现方案
你可以将专属Context的Provider放到对应Stack.Screen的内部渲染逻辑中,既满足导航器的语法要求,也能实现只有指定页面能访问对应Context,同时不会污染App.js的全局代码。
方案1:使用Stack.Screen的children回调写法(最简便)
直接在对应页面的Stack.Screen标签内写返回JSX的回调函数,把Provider包裹在页面组件外层即可。
改造后App.js代码
移除全局不需要的专属Context,只保留全局通用的Provider:
export default function App() { return ( <NavigationContainer> <StatusBar translucent /> {/* 仅保留全局通用的Provider,非全页面使用的Context都移到路由层 */} <WarningProvider> <Routes /> </WarningProvider> </NavigationContainer> ); }
改造后AppRoutes.js代码
export default function Routes() { return ( <Stack.Navigator initialRouteName={'Screen1'} screenOptions={{ headerShown: false, }}> <Stack.Screen name="Screen1" component={Screen1} /> {/* 仅给Screen2注入专属Context */} <Stack.Screen name="Screen2"> {() => ( <Screen2Context.Provider> <Screen2 /> </Screen2Context.Provider> )} </Stack.Screen> {/* 仅给Screen3注入专属Context */} <Stack.Screen name="Screen3"> {() => ( <Screen3Context.Provider> <Screen3 /> </Screen3Context.Provider> )} </Stack.Screen> </Stack.Navigator> ); }
如果需要把路由参数传给Context的value,可以直接接收回调参数中的route对象:
<Stack.Screen name="Screen2"> {({route, navigation}) => ( <Screen2Context.Provider value={{id: route.params.id, navigation}}> <Screen2 /> </Screen2Context.Provider> )} </Stack.Screen>
方案2:高阶组件封装(适合复用场景)
如果同一个Context需要给多个页面使用,你可以封装高阶组件,在路由中直接传入包装后的页面组件即可:
// 高阶组件:给目标组件包裹Screen2Context const withScreen2Context = (Component) => { return (props) => ( <Screen2Context.Provider> <Component {...props} /> </Screen2Context.Provider> ) } // 路由中直接使用 <Stack.Screen name="Screen2" component={withScreen2Context(Screen2)} />
内容的提问来源于stack exchange,提问作者Ademar-SJ
相关产品推荐
相关产品推荐

