One SVG to Rule Them All: The Dynamic Way

When you ship icons in a React Native app, it's tempting to export a separate file for every stroke width and color. You don't have to. SVG's presentation attributes inherit, and react-native-svg-transformer runs your .svg files through SVGR, which spreads incoming component props onto the root <svg> element. Pass color and strokeWidth as props once; SVG inheritance handles the rest.

Setup

1bun add react-native-svg 2bun add -d react-native-svg-transformer

Route .svg files through the transformer in metro.config.js (RN 0.72+ form):

1const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config') 2 3const defaultConfig = getDefaultConfig(__dirname) 4const { resolver: { sourceExts, assetExts } } = defaultConfig 5 6module.exports = mergeConfig(defaultConfig, { 7 transformer: { 8 babelTransformerPath: require.resolve('react-native-svg-transformer'), 9 }, 10 resolver: { 11 assetExts: assetExts.filter((ext) => ext !== 'svg'), 12 sourceExts: [...sourceExts, 'svg'], 13 }, 14})

The icon file

Strip everything you'd otherwise hard-code. Use currentColor for the stroke and omit stroke-width so it inherits from the prop:

1<!-- MyIcon.svg, an X --> 2<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"> 3 <path stroke="currentColor" d="M7 7l10 10M7 17l10-10" /> 4</svg>

Use it

1import MyIcon from './path/to/MyIcon.svg' 2 3export default function App() { 4 return ( 5 <View> 6 <MyIcon width={24} height={24} color="red" strokeWidth={2} /> 7 </View> 8 ) 9}

What's actually happening:

  • SVGR's default expandProps spreads every prop you pass to <MyIcon> onto the generated root <Svg> element.
  • react-native-svg resolves currentColor on descendants against the nearest ancestor's color prop. color="red" on <Svg> paints the stroke red.
  • SVG attribute inheritance carries stroke-width from <Svg> down to any <path> that hasn't set its own. strokeWidth={2} on the component is the only place stroke width is defined, so every path takes it.

The same pattern works for any inheritable presentation attribute — fill, stroke-linecap, stroke-linejoin, stroke-opacity, font-family. Strip them from the source SVG, pass them as component props.