首页 > 解决方案 > 如何为 React Navigation 的 Tab.Screen 构建可重用组件?

问题描述

学习 React Navigation 6 我正在使用旧的 Tab Navigator 并对其进行升级,重点是 DRY 原则:

旧标签导航器:

<Tab.Navigator screenOptions={tabOptions}>
  <Tab.Screen
    name={routes.HOME}
    component={HomeScreen}
    options={{
      tabBarIcon: ({ focused }) => (
        <View
          style={{
            position: 'absolute',
            top: 20,
          }}
        >
          <FontAwesome5
            name="home"
            size={20}
            color={focused ? colors.red : colors.grey}
          ></FontAwesome5>
        </View>
      ),
    }}
    listeners={({ navigation, route }) => ({
      tabPress: e => {
        Animated.spring(tabOffsetValue, {
          toValue: 0,
          useNativeDriver: true,
        }).start()
      },
    })}
  />
  <Tab.Screen
    name={routes.SEARCH}
    component={SearchScreen}
    options={{
      tabBarIcon: ({ focused }) => (
        <View
          style={{
            position: 'absolute',
            top: 20,
          }}
        >
          <FontAwesome5
            name="search"
            size={20}
            color={focused ? colors.red : colors.grey}
          ></FontAwesome5>
        </View>
      ),
    }}
    listeners={({ navigation, route }) => ({
      tabPress: e => {
        Animated.spring(tabOffsetValue, {
          toValue: getWidth(),
          useNativeDriver: true,
        }).start()
      },
    })}
  />
</Tab.Navigator>

因为我在重复options并且我没有使用 Font Awesome 以外的任何图标,所以我尝试构建一个组件:

const TabScreen = ({ name, component, icon }) => {
  return (
    <Tab.Screen
      name={name}
      component={component}
      options={{
        tabBarIcon: ({ focused }) => (
          <View style={styles.tabBar}>
            <FontAwesome5
              name={icon}
              size={20}
              color={focused ? colors.red : colors.gray}
            ></FontAwesome5>
          </View>
        ),
      }}
      listeners={({ navigation, route }) => ({
        tabPress: e => {
          Animated.spring(tabOffsetValue, {
            toValue: 0,
            useNativeDriver: true,
          }).start()
        },
      })}
    />
  )
}

但我在终端的错误是:

Error: A navigator can only contain 'Screen', 'Group' or 'React.Fragment' as its direct children (found 'TabScreen' for the screen 'Home'). To render this component in the navigator, pass it in the 'component' prop to 'Screen'. 

所以我只为options

tabScreenIcon.js:

const tabScreenIcon = name => {
  return {
    tabBarIcon: ({ focused }) => (
      <View style={styles.icon}>
        <FontAwesome5 name={name} size={20} color={focused ? colors.red : colors.grey} />
      </View>
    ),
  }
}
const styles = StyleSheet.create({
  icon: {
    position: 'absolute',
    top: 20,
  },
})

应用程序.js:

<Tab.Screen
  name={routes.HOME}
  component={HomeScreen}
  options={tabScreenIcon('home')}
  listeners={({ navigation, route }) => ({
    tabPress: e => {
      Animated.spring(tabOffsetValue, {
        toValue: 0,
        useNativeDriver: true,
      }).start()
    },
  })}
/>
<Tab.Screen
  name={routes.SEARCH}
  component={SearchScreen}
  options={tabScreenIcon('search')}
  listeners={({ navigation, route }) => ({
    tabPress: e => {
      Animated.spring(tabOffsetValue, {
        toValue: getWidth(),
        useNativeDriver: true,
      }).start()
    },
  })}
/>

现在我正在尝试让我的动画工作,而我的选项卡屏幕仍然不是 DRY 有没有办法构建一个Tab.Screen我可以通过 propsnamecomponent动画值的可重复使用的动画?

标签: reactjsreact-nativereact-navigationdry

解决方案



推荐阅读