React Navigation:Drawer导航中Header与Screen如何共享状态?
问题根源
你现在的代码里,MyScreenHeader是作为Drawer.Screen的options.header传入的,它的渲染层级在MyScreenProvider外面——MyScreenProvider只包裹了MyScreen的内容,而Header是由导航器负责渲染的,不在这个Provider的覆盖范围内,所以useContext拿不到有效值,只能返回初始的null。
两种可行解决方案
方案1:把Context Provider提到导航器外层
让整个Drawer Navigator都处于MyScreenProvider的包裹下,这样Header和Screen就能共享同一个Context:
const MyScreenContext = createContext(null); const MyScreenProvider = ({children})=>{ const [state,setState] = useState(""); return <MyScreenContext.Provider value={{state,setState}}>{children}</MyScreenContext.Provider> } const MyScreenHeader = ()=>{ const { state, setState } = useContext(MyScreenContext); // 这里可以正常读写输入值了 return ( <View> <TextInput value={state} onChangeText={setState} placeholder="请输入内容" /> </View> ) } const MyScreen = ()=>{ const { setState } = useContext(MyScreenContext); // 清空输入的方法 const clearInput = () => setState(""); return ( <View style={{flex:1, justifyContent:'center', alignItems:'center'}}> <Button title="清空输入框" onPress={clearInput} /> {/* 其他页面内容 */} </View> ) }; // 把Provider包在导航器外面 export default function App() { return ( <MyScreenProvider> <DrawerNavigator> <Drawer.Screen name={"MyScreen"} component={MyScreen} options={{ header: MyScreenHeader, }} /> {/* 其他页面 */} </DrawerNavigator> </MyScreenProvider> ) }
方案2:在Screen内部动态设置Header(更推荐)
用navigation.setOptions在MyScreen内部动态生成Header,这样Header就处于Screen的状态作用域内,甚至不用Context就能直接传值:
// 直接给Header传状态和修改函数 const MyScreenHeader = ({inputValue, setInputValue})=>{ return ( <View> <TextInput value={inputValue} onChangeText={setInputValue} placeholder="请输入内容" /> </View> ) } const MyScreen = ({navigation})=>{ const [inputValue, setInputValue] = useState(""); // 组件挂载后动态设置Header useEffect(() => { navigation.setOptions({ header: () => <MyScreenHeader inputValue={inputValue} setInputValue={setInputValue} /> }); }, [navigation, inputValue]); // 清空输入 const clearInput = () => setInputValue(""); return ( <View style={{flex:1, justifyContent:'center', alignItems:'center'}}> <Button title="清空输入框" onPress={clearInput} /> </View> ) }; // 导航器配置保持不变 <Drawer.Screen name={"MyScreen"} component={MyScreen} />
这个方案更轻量,不会因为单个页面的状态污染全局Context,适合这种单个页面Header和内容交互的场景。
内容的提问来源于stack exchange,提问作者Endrit Shabani
相关产品推荐
相关产品推荐

