React Navigation自定义抽屉不重绘:切换项时样式未更新
我之前也碰到过一模一样的问题!你遇到的核心问题是依赖props.activeItemKey来判断激活状态不可靠,这个属性并不会在路由切换时自动触发组件重渲染,导致你的样式切换逻辑失效。下面是具体的排查和修复方案:
问题根源
在自定义抽屉组件DrawerScreen中,你通过props.activeItemKey对比菜单项的key来设置样式,但React Navigation的自定义contentComponent并不会实时更新这个activeItemKey属性,或者说这个属性的更新没有触发组件的重绘,导致切换菜单时样式不会变化。另外注意你的组件名拼写错误:DrawserScreen应该是DrawerScreen,虽然大概率是笔误,但也可能影响组件的正常渲染。
修复方案:直接从导航状态获取当前激活路由
我们可以直接从导航实例的状态中获取当前活跃的路由信息,这样就能实时响应路由切换,触发样式更新。
针对React Navigation 5+版本(推荐)
使用useNavigation和useRoute钩子来获取当前路由状态:
import React from 'react'; import { ScrollView, SafeAreaView, TouchableHighlight, View, Text } from 'react-native'; import { useNavigation, useRoute } from '@react-navigation/native'; const DrawerScreen = props => { const navigation = useNavigation(); const currentRoute = useRoute(); const totalitem = props.items; return( <ScrollView style={{backgroundColor:'#000'}}> <SafeAreaView forceInset={{ top: 'always', horizontal: 'never' }}> { totalitem.map((ritem,i)=>{ // 对比路由名称,更直观可靠 const isActive = ritem.routeName === currentRoute.name; const txtstyle = isActive ? styles.draweritemstxt_active : styles.draweritemstxt_inactive; return( <TouchableHighlight key={i} activeOpacity={0.9} onPress={()=> props.navigation.navigate(ritem.routeName)} style={styles.draweritems} > <View> <Text style={txtstyle}>{_convertRouteToTitle(ritem.routeName)}</Text> </View> </TouchableHighlight> ); }) } </SafeAreaView> </ScrollView> ); } // 别忘了定义你的样式 const styles = { draweritems: { // 你的菜单项容器样式 }, draweritemstxt_active: { color: '#fff', fontWeight: 'bold', // 其他激活样式 }, draweritemstxt_inactive: { color: '#aaa', // 其他未激活样式 } }; export default DrawerScreen;
针对React Navigation 4及以下版本
如果还在使用旧版本,可以直接从props.navigation.state中获取当前活跃路由:
const DrawerScreen = props => { // 获取当前活跃路由的key const currentActiveKey = props.navigation.state.routes[props.navigation.state.index].key; const totalitem = props.items; return( <ScrollView style={{backgroundColor:'#000'}}> <SafeAreaView forceInset={{ top: 'always', horizontal: 'never' }}> { totalitem.map((ritem,i)=>{ const txtstyle = ritem.key === currentActiveKey ? styles.draweritemstxt_active : styles.draweritemstxt_inactive; return( <TouchableHighlight key={i} activeOpacity={0.9} onPress={()=> props.navigation.navigate(ritem.key)} style={styles.draweritems} > <View> <Text style={txtstyle}>{_convertRouteToTitle(ritem.routeName)}</Text> </View> </TouchableHighlight> ); }) } </SafeAreaView> </ScrollView> ); }
额外检查点
- 确认
styles.draweritemstxt_active和styles.draweritemstxt_inactive确实有明显的样式差异(比如颜色、字体粗细),避免因为样式本身无区别导致看起来没变化。 - 确保
_convertRouteToTitle函数能正确转换路由名称,不影响渲染逻辑。
这样修改后,切换抽屉选项时,组件会实时获取当前活跃路由,正确应用激活/未激活样式,触发重绘。
内容的提问来源于stack exchange,提问作者FeelRightz
相关产品推荐
相关产品推荐

