Effortlessly Add SVG Files to Your React Native Expo App
Published: 2023-06-26 17:44:14

Hello friends,

Today, I will share with you a reliable method to incorporate SVG files into React Native applications. There are two primary approaches that I have found effective: utilizing the React Native SVG transformer or the react-native-svg package independently.

## Using the react-native-svg-transformer package
The React Native SVG transformer enables seamless importing of SVG files in your React Native projects, similar to how you would in a web application when utilizing libraries like SVGR to transform imported SVG images into React components.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hez8onfnj8z255ixzt2m.png)

However, there are a couple of significant disadvantages to consider:

The "react-native-svg-transformer" package is primarily designed for the development environment. By default, when running a React Native project with Expo, the Metro bundler handles the transformation of SVG files into React Native components during development. Nevertheless, in the production environment, Expo bundles and optimizes the JavaScript code and assets in advance, omitting the SVG transformation step.

To integrate SVG files into a React Native Expo app in the production environment, you have a few options:

- Convert SVG to React Native components.
- Utilize pre-converted SVG components.
- Load SVGs as static assets.

The second reason to consider is **the lack of flexibility**. We use SVG because it allows for scalability without compromising quality, and one of the key advantages of SVG files is the ability to dynamically change styles such as color. While the react-native-svg-transformer package offers ways to configure the color change through the svgr file, I have personally faced difficulties in achieving this. If you have successfully accomplished it, please share your insights in the comments.

**The recommended solution is:**

## Using SVG files as React Native SVG components
The benefits of using React Native SVG components with SVG files are as follows:

1. Dynamic rendering: React Native SVG components facilitate dynamic rendering and manipulation. You can pass props to the SVG components to customize their appearance, such as changing colors, sizes, or positions. This flexibility allows you to create interactive and responsive UI elements based on user interactions or dynamic data.

2. Consistent styling: By utilizing React Native's styling system, you can apply consistent styles and themes to your SVG components. Styles can be defined and reused across different components, ensuring a cohesive and visually appealing UI.

3. Performance optimization: React Native SVG components are optimized for rendering on mobile devices. They leverage the native rendering capabilities of the platform, resulting in efficient and high-performance UI rendering. Additionally, techniques like memoization or PureComponent can be applied to optimize component rendering, especially when dealing with large or frequently changing SVG components.
 
4. Integration with React Native ecosystem: By using React Native SVG components, you can leverage the extensive ecosystem of React Native libraries and tools. You can combine SVG components with other React Native components, animations, navigation, and state management solutions, enhancing the functionality and interactivity of your app.
 
5. Cross-platform compatibility: React Native SVG components seamlessly work across different platforms, including iOS and Android. This ensures consistent user experiences regardless of the target platform.

6. Scalability and reusability: Converting SVG files to React Native components enables you to create a library of reusable components. These components can be easily reused throughout your project or shared across multiple projects, improving development efficiency and reducing duplication.

However, the challenge lies in manually converting SVG files to JSX files, or utilizing other tools such as the [svg-to-react-native](https://transform.tools/svg-to-react-native) website. If you have a substantial number of SVG files like me, this process becomes tedious. Hence, I have asked ChatGPT to generate a Linux Bash script to automate the conversion from SVG to JSX files. Here's the resulting script:

```
#!/bin/bash

# Check if svgr is installed
if ! command -v svgr &> /dev/null; then
    echo "svgr is not installed. Please install it by running: npm install -g @svgr/cli"
    exit 1
fi

# Create a directory for the output files
output_dir="output"
mkdir -p "$output_dir"

# Convert SVG files to React Native SVG files
for file in *.svg; do
    filename=$(basename "$file")
    output_file="${filename%.*}.js"
    svgr --native --no-dimensions "$file" --out-dir "$output_dir"
    mv "$output_dir/$filename" "$output_dir/$output_file"
done

echo "Conversion completed. React Native SVG files are located in the '$output_dir' directory."
```

Before running the above code, you must install the react-native-svg package in your React Native project using the command:
`expo install react-native-svg`

Additionally, you need to install the svgr package globally on your machine using the command:
`sudo npm install -g @svgr/cli`

Once you have completed these installations, create a Bash file (e.g., svgrconverter.bash) in the directory where the SVG files are located. Give the file executable permission using the command:
`chmod +x svgrconverter.bash`

Finally, run the file using the command:
`./svgrconverter.bash`

This script will create a new folder named "output" and convert all SVG files into JSX format as JS files.

Now, you can pass props to the SVG component, such as width and height. However, if the color implementation is present within the Path tag like this:

```
<Svg
    xmlns="http://www.w3.org/2000/svg"
    fill="none"
    viewBox="0 0 18 18"
    {...props}
  >
    <Path
      fill='#000'
      d=""
    />

```
The fill prop will not work as expected when using the component, like `<Share fill="#fff" width={24} height={24} />`.

To resolve this, you need to modify the React Native SVG file as follows:

```
<Svg
    xmlns="http://www.w3.org/2000/svg"
    fill="none"
    viewBox="0 0 18 18"
    {...props}
  >
    <Path
      fill={props.color || '#000'}
      d=""
    />

```

Therefore, to change the path color, you can use the following syntax: `<Share color="#fff" width={24} height={24} />`. 
However, modifying each file individually can be overwhelming. To address this, I requested ChatGPT to generate a new script that automatically changes the fill attribute in the Path tag to the format mentioned above, but only if a single Path tag exists.

I have merged both scripts into a single file:

```
#!/bin/bash

# Check if svgr is installed
if ! command -v svgr &> /dev/null; then
    echo "svgr is not installed. Please install it by running: npm install -g @svgr/cli"
    exit 1
fi

# Create a directory for the output files
output_dir="output"
mkdir -p "$output_dir"

# Convert SVG files to React Native SVG files
for file in *.svg; do
    filename=$(basename "$file")
    output_file="${filename%.*}.js"
    svgr --native --no-dimensions "$file" --out-dir "$output_dir"
    mv "$output_dir/$filename" "$output_dir/$output_file"
done

echo "Conversion completed. React Native SVG files are located in the '$output_dir' directory."

# The second script
# Loop through each JS file in the output_dir
for file in "$output_dir"/*.js; do
    # Check if the JS file has a single Path tag
    path_count=$(grep -o '<Path' "$file" | wc -l)
    if [[ $path_count -eq 1 ]]; then
        # Replace the fill attribute with fill={props.color || '#000'} only in the Path tag
        sed -E -i.bak 's/fill="#000"/fill={props.color || '\''#000'\''}/' "$file"
        rm "$file.bak"  # Remove the backup file created by sed
        echo "Conversion successful: $file"
    else
        echo "Skipped: $file (The SVG file does not have a single Path tag.)"
    fi
done

echo "All JS files converted."

```
Feel free to make any necessary modifications to fit your specific requirements. Thank you for reading, and don't forget to follow me on [GitHub](https://github.com/7codo) and check out my portfolio at [7codo.com](7codo.com).