You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bottom Tabs激活态颜色不切换,focused值频繁在true/false间跳变求助

React Navigation Bottom Tabs 焦点状态异常问题

我想给底部标签栏设置样式:当tab处于focused状态时,改变文本颜色并显示底部边框来标记激活状态。但发现focused回调会在true和false之间来回切换,最终所有标签的focused值都变成false。

原代码

export default function TabLayout() {
  const { theme } = useTheme();
  return (
    <Tabs
      screenOptions={{
        title: '',
        headerShown: false,
      }}
    >
      <Tabs.Screen
        name="index"
        options={{
          tabBarLabelStyle: { color: theme.colors.main.dark, fontSize: 12 },
          tabBarLabel: 'Main',
          tabBarIcon: args => {
            console.log('Main args');
            console.log(args);

            return <Feather name="home" size={24} /> />;
          },
        }}
      />
      <Tabs.Screen
        name="search"
        options={{
          tabBarLabelStyle: { color: theme.colors.main.dark, fontSize: 12 },
          tabBarLabel: 'Search',
          tabBarIcon: args => {
            console.log('Search args');
            console.log(args);

            return <Feather name="search" size={24} />;
          },
        }}
      />
    </Tabs>
  );
}

控制台输出

LOG  Home args
LOG  {"color": "rgb(0, 122, 255)", "focused": true, "size": 25}
LOG  Home args
LOG  {"color": "#8E8E8F", "focused": false, "size": 25}
LOG  Search args
LOG  {"color": "rgb(0, 122, 255)", "focused": true, "size": 25}
LOG  Search args
LOG  {"color": "#8E8E8F", "focused": false, "size": 25}
LOG  Home args
LOG  {"color": "rgb(0, 122, 255)", "focused": true, "size": 25}
LOG  Home args
LOG  {"color": "#8E8E8F", "focused": false, "size": 25}
LOG  Search args
LOG  {"color": "rgb(0, 122, 255)", "focused": true, "size": 25}
LOG  Search args
LOG  {"color": "#8E8E8F", "focused": false, "size": 25}

问题原因

  1. 语法错误触发渲染异常:第一个tab的tabBarIcon返回语句多了一个/>,导致React渲染出错,进而引发Navigation内部状态反复更新,focused值来回切换。
  2. 静态options配置引发重复渲染:用静态对象定义options,当组件依赖的theme变化时,整个tab配置会被重新创建,触发焦点状态反复重置。
  3. 固定样式覆盖动态状态:给tabBarLabelStyle固定了颜色,没有根据focused状态动态调整,既达不到样式需求,还会干扰Navigation对激活状态的判断逻辑。

修复方案

修正后的代码

import { useTheme } from '@react-navigation/native';
import { Feather } from '@expo/vector-icons';
import { Tabs } from '@react-navigation/bottom-tabs';

export default function TabLayout() {
  const { theme } = useTheme();
  return (
    <Tabs
      screenOptions={{
        title: '',
        headerShown: false,
      }}
    >
      <Tabs.Screen
        name="index"
        // 使用函数式options,动态接收focused状态参数
        options={({ focused }) => ({
          tabBarLabel: 'Main',
          tabBarLabelStyle: {
            // 根据focused切换文本颜色
            color: focused ? theme.colors.main.dark : '#8E8E8F',
            fontSize: 12,
            // 激活时显示底部边框
            borderBottomWidth: focused ? 2 : 0,
            borderBottomColor: theme.colors.main.dark,
          },
          tabBarIcon: () => (
            <Feather 
              name="home" 
              size={24} 
              color={focused ? theme.colors.main.dark : '#8E8E8F'} 
            />
          ),
        })}
      />
      <Tabs.Screen
        name="search"
        options={({ focused }) => ({
          tabBarLabel: 'Search',
          tabBarLabelStyle: {
            color: focused ? theme.colors.main.dark : '#8E8E8F',
            fontSize: 12,
            borderBottomWidth: focused ? 2 : 0,
            borderBottomColor: theme.colors.main.dark,
          },
          tabBarIcon: () => (
            <Feather 
              name="search" 
              size={24} 
              color={focused ? theme.colors.main.dark : '#8E8E8F'} 
            />
          ),
        })}
      />
    </Tabs>
  );
}

关键修复点

  • 删掉第一个tabBarIcon里多余的/>,修复渲染错误。
  • 将options改为函数形式,接收focused参数,动态计算样式,避免静态配置导致的重复渲染和状态冲突。
  • 根据focused状态设置文本颜色和底部边框,实现激活样式需求。

内容的提问来源于stack exchange,提问作者Phil Lucks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 03:09:54