为什么React Native的Bottom Tabs Navigator会发生不必要的重渲染?
问题原因
- 你在
MainTabScreen内部直接定义了tabBarOptions对象、每个Tab.Screen的options.tabBarIcon回调函数,组件每次渲染都会生成新的引用,被判定为props变更触发重渲染 - 你没有对
MainTabScreen做缓存处理,只要上层组件触发重渲染就会连带它重渲染 - 排查
AuthStack中的authContext值,如果你是直接在Provider的value属性里写对象字面量,每次AuthStack渲染都会生成新的context值,也会触发所有下层组件重渲染
修复步骤
1. 缓存MainTabScreen的静态配置
将不需要跟随组件状态变化的配置抽到组件外部,或者用useMemo缓存引用,修改后的MainTabScreen.js代码如下:
import React, { useMemo } from 'react' // 其他导入省略 // 静态配置抽到组件外部 const TAB_BAR_OPTIONS = { showLabel: false, style: { position: "absolute", height: 40, bottom: 0, right: 0, left: 0, backgroundColor: "#fff", }, } const MainTabScreen = () => { // 缓存各个tab的配置,避免每次渲染生成新引用 const screenOptions = useMemo(() => ({ MainHome: { tabBarIcon: ({ focused }) => ( <Icon.Home color={focused ? "#f62459" : "#302f2f"} height={28} width={28} /> ) }, MainCart: { tabBarIcon: ({ focused }) => ( <Icon.ShoppingCart color={focused ? "#f62459" : "#302f2f"} width={28} height={28} /> ) }, MainProfile: { tabBarIcon: ({ focused }) => ( <Icon.User color={focused ? "#f62459" : "#302f2f"} height={28} width={28} /> ) } }), []) return ( <Tab.Navigator tabBarOptions={TAB_BAR_OPTIONS}> <Tab.Screen name="MainHome" component={MainHomeScreen} options={screenOptions.MainHome} /> <Tab.Screen name="MainCart" component={MainCartScreen} options={screenOptions.MainCart} /> <Tab.Screen name="MainProfile" component={MainProfileScreen} options={screenOptions.MainProfile} /> </Tab.Navigator> ); }; // 用React.memo包裹导出,浅比较props阻止不必要重渲染 export default React.memo(MainTabScreen);
2. 缓存AuthContext的value值
修改AuthStack.js,用useMemo缓存context的value,避免每次渲染生成新对象:
const AuthStack = () => { const initialLoginState = { isLoading: true, accessToken: null, }; // 其他身份验证逻辑... // 缓存context值,依赖变化时才更新引用 const authContext = useMemo(() => ({ // 你原本的context属性和方法都放在此处 login: () => {}, logout: () => {} }), [/* 把依赖的状态变量填入此处 */]) return ( <AuthContext.Provider value={authContext}> {loginState.accessToken !== null ? <AppStack /> : <RootStack />} </AuthContext.Provider> ); };
额外说明
底部标签导航切换时,Tab导航器本身的状态变化触发的少量重渲染是正常现象,只要各个子页面(Home、Cart、Profile)没有出现不必要的重渲染,就不会对性能造成明显影响,不需要过度优化。
内容的提问来源于stack exchange,提问作者Ayush Kumar
相关产品推荐
相关产品推荐

