typescriptreact-nativeexpo

How to use @expo/vector-icons dynamically through props in typescript react native app?


react native app with typescript and I'm trying to create icon button that uses @expo/vector-icons with Fontawesome or MaterialIcon dynamically by trying to pass a name as a string via props.

I think the issue is this, BUT don't know how to solve it. Any ideas? Suggestions? Also feel free to criticize other code.

Below is my IconButton component that receives the name prop

import { Ionicons, MaterialIcons, FontAwesome } from 
 "@expo/vector-icons";

const star = "star";

type Props = {
  name: keyof typeof MaterialIcons.glyphMap;
  color: string;
  onPress(): void;
};

export default function IconButton(props: Props) {
  return (
    <Ionicons.Button name={props.name} size={24} color={props.color} />
  );
}

Fontawesome expo vector expected properties

the 'name' property is the issue here.

This code is from a screen using IconButton where I pass the name as a string.

useLayoutEffect(() => {
    navigation.setOptions({
      headerRight: () => {
        return (
          <IconButton
            onPress={headerButtonPressHandler}
            name="star"
            color="gray"
          />
        );
      },
    });
  }, [navigation, headerButtonPressHandler]);

name property error

edit: updated code but still there is error on name

updated code

this is where I use IconButton and pass in name


Solution

  • In your Props type, name should not be a string - it should only allow names that exist in your icon set. If you look through the issues on Github for expo/vector-icons, you can see that others are also facing the same problem, and one has posted a solution:

    import { MaterialIcons } from '@expo/vector-icons';
    
    type Props = {
      materialIconName: keyof typeof MaterialIcons.glyphMap;
    }
    

    This solution and related discussion can be found here: https://github.com/expo/vector-icons/issues/153#issuecomment-752769305

    One of the library authors also offers this solution:

    type MaterialIconName = React.ComponentProps<typeof MaterialIcons>['name'];
    const iconName: MaterialIconName =  '3d-rotation'
    

    https://github.com/expo/vector-icons/issues/153#issuecomment-787130328