React Native Material顶部标签页状态变更未触发重渲染问题求助
问题根因
你遇到的重渲染失败和Hook顺序警告,核心是Screen组件的children属性使用方式不符合React Navigation规范:
你直接将CulturalHeritageList组件函数作为children属性值传递给Screen,相当于在Screen的内部渲染逻辑中直接执行CulturalHeritageList的函数体,所有内部Hook(useQuery、useNavigation等)都会被挂载到Screen所属的父组件上下文。两个Tab都复用同一个组件函数时,就会导致父组件的Hook调用顺序在渲染不同Tab时发生错乱,React检测到Hook规则被破坏后会终止重渲染流程,因此你会看到控制台打印的loading和数据已经更新,但页面始终停留在加载状态。
修复方案
修改Navigation.tsx中的Screen配置,有两种可选的正确写法:
写法1:使用component属性传递组件(无额外传参时推荐)
直接将组件通过component属性传递,React Navigation会自动将其作为独立组件实例挂载,Hook会注册到组件自身的上下文,不会出现顺序错乱问题:
<CulturalHeritageTab.Screen name="Tour" component={CulturalHeritageList} /> <CulturalHeritageTab.Screen name="Exibition" component={CulturalHeritageList} />
写法2:children属性传入返回JSX的函数(需要额外传参时使用)
如果需要给CulturalHeritageList传递自定义参数,就给children属性传入一个返回组件JSX的函数,保证组件作为独立实例挂载:
<CulturalHeritageTab.Screen name="Tour" children={() => <CulturalHeritageList customParam="tour" />} /> <CulturalHeritageTab.Screen name="Exibition" children={() => <CulturalHeritageList customParam="exhibition" />} />
可选优化
如果两个Tab需要展示不同的筛选数据,你可以在CulturalHeritageList中通过useRoute钩子获取当前Tab的name,动态调整useQuery的查询参数即可。
修改完成后Hook顺序警告会自动消失,useQuery的状态更新就能正常触发组件重渲染。
内容的提问来源于stack exchange,提问作者SlothOverlord

