One SVG to Rule Them All: The Dynamic Way
Tags: javascript, reactnative
Published: 2023-04-13 16:37:29

When working with SVG icons in a React Native app, it's quite common to end up with numerous variations of the same icon, differing only in stroke width, color, or other styling attributes. This can lead to an ever-growing list of assets, making it difficult to manage and maintain your icons. Instead, we can leverage the power of SVG's dynamic nature by using `strokeWidth` and `currentColor` to make our icons flexible and adaptable.

In this blog post, we'll explore how to dynamically configure SVG elements in a React Native app using `strokeWidth` and `currentColor`. By doing so, you can easily change the appearance of your SVG components by passing props to them, eliminating the need for multiple variations of the same icon. This approach results in a cleaner codebase and improves maintainability. We'll be using the r`eact-native-svg` and `react-native-svg-transformer` packages to accomplish this.

## The Benefits of a Dynamic Approach

There are several advantages to dynamically configuring SVG elements compared to using multiple inline SVGs or separate icon files:

**Reduced Asset Management:** Instead of creating a separate icon file for each variation, you can maintain a single SVG file that adapts its appearance based on the props you pass. This simplifies your codebase and reduces the number of files you need to manage.

**Improved Performance:** Using a single SVG file reduces the number of assets that need to be fetched and rendered, which can improve the performance of your app.

**Easier Theming and Styling:** By passing props like color and strokeWidth, you can easily change the appearance of your icons across your entire app, making it easier to implement themes and adjust styles.

**Greater Flexibility:** Using a dynamic approach makes it easier to update the appearance of your icons in response to user interactions, such as changing colors on hover or focus events.

Now, let's dive into the implementation details and create a flexible SVG component that dynamically adapts to the props passed.

## Getting Started

First, let's install the necessary packages:

```bash
npm install react-native-svg
npm install --save-dev react-native-svg-transformer
```

Now, configure the metro.config.js file to use the `react-native-svg-transformer`:

```js
const { getDefaultConfig } = require("metro-config");

module.exports = (async () => {
  const {
    resolver: { sourceExts, assetExts },
  } = await getDefaultConfig();
  return {
    transformer: {
      babelTransformerPath: require.resolve("react-native-svg-transformer"),
      getTransformOptions: async () => ({
        transform: {
          experimentalImportSupport: false,
          inlineRequires: false,
        },
      }),
    },
    resolver: {
      assetExts: assetExts.filter((ext) => ext !== "svg"),
      sourceExts: [...sourceExts, "svg"],
    },
  };
})();
```

## Creating an SVG Component

Let's create an SVG file called `MyIcon.svg` with a path element that accepts `strokeWidth` and `currentColor`:

```js
<!-- MyIcon.svg -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
  <path stroke="currentColor" strokeWidth="{strokeWidth}" d="M7 7l10 10M7 17l10-10" />
</svg>
```

Here, we use the `currentColor` value to make the stroke color inherit the `color` from the color CSS property. We also use a placeholder value `{strokeWidth}` to accept the stroke width as a prop.

## Using the SVG Component

Now, let's import the SVG file as a component in our React Native component and pass `color` and `strokeWidth` props to it:

```javascript
import React from 'react';
import { View } from 'react-native';
import MyIcon from './path/to/MyIcon.svg';

const App = () => {
  return (
    <View>
      <MyIcon width={24} height={24} color="red" strokeWidth={2} />
    </View>
  );
};

export default App;
```

With this setup, the imported SVG component's stroke color and stroke width will be dynamically set to the values of the `color` and `strokeWidth` props, respectively.

By using the `currentColor` and `strokeWidth` attributes in your SVG elements, you can create flexible and dynamic components that easily adapt to your design requirements. This approach can be extended to other stroke-related properties like `strokeLinecap`, `strokeLinejoin`, and `strokeOpacity`. Just add the corresponding attributes to your SVG file and pass them as props to your imported SVG component.