React Native SVG Transformer
React Native SVG Transformer enables developers to import SVG files directly into their React Native projects, treating them as React components. This mimics the development experience of web applications using libraries like SVGR, facilitating code sharing between web and mobile platforms. The package is currently at version 1.5.3 and demonstrates an active release cadence, frequently updating to support new versions of React Native and Expo SDK, as indicated by multiple releases within recent months addressing compatibility issues. It's a crucial tool for projects aiming for scalable vector graphics that can be dynamically styled and manipulated, differentiating itself by seamlessly integrating SVG assets into the Metro bundler workflow for both bare React Native and Expo projects.
Common errors
-
Unable to resolve module `./path/to/icon.svg`
cause Metro bundler is not configured to recognize '.svg' files as source extensions or to use the SVG transformer.fixEnsure `metro.config.js` is correctly configured: `assetExts` should filter out 'svg', and `sourceExts` should include 'svg'. Restart Metro with `npm start -- --reset-cache` or `yarn start --reset-cache`. -
Invariant Violation: requireNativeComponent: `RNSVG...` was not found in the UIManager.
cause `react-native-svg` native modules are not correctly linked, especially common on iOS or Android after installation or upgrades.fixFor iOS, navigate to your `ios` directory and run `pod install`. For Android, ensure a clean build by running `cd android && ./gradlew clean` and then rebuilding your app. Ensure `react-native-svg` is properly installed and linked according to its documentation. -
TypeError: transformer.transform is not a function
cause The `babelTransformerPath` in `metro.config.js` is pointing to an incorrect or non-existent transformer module, or there's a version mismatch between packages.fixVerify that `babelTransformerPath` is set correctly to either `require.resolve("react-native-svg-transformer/react-native")` or `require.resolve("react-native-svg-transformer/expo")` based on your project type and that `react-native-svg-transformer` is installed. Check for conflicts if multiple transformers are used. -
Error: While trying to resolve module `metro/src/reactNativeTransformer` from file `/node_modules/react-native-svg-transformer/index.js`, the package `metro` is not found.
cause This error often occurs in older configurations or when `react-native-svg-transformer`'s internal dependency on `metro`'s transformer path is not met, typically in Expo projects when using the bare React Native transformer path.fixFor Expo projects, ensure your `metro.config.js` uses `require.resolve("react-native-svg-transformer/expo")`. If the issue persists, review Expo SDK and `react-native-svg-transformer` compatibility.
Warnings
- breaking Version 1.0.0 introduced breaking changes, dropping support for `react-native` versions older than 0.59 and `react-native-svg` versions older than 12. Projects on older versions must upgrade their React Native and `react-native-svg` dependencies before updating to `react-native-svg-transformer` v1.0.0 or newer.
- gotcha Metro configuration is highly sensitive to the project type (bare React Native vs. Expo) and the React Native/Expo SDK version. Incorrectly configured `metro.config.js` is the most common cause of issues.
- gotcha SVG files with non-globally unique IDs can lead to rendering artifacts when multiple SVGs are inlined as React components, as their internal IDs may conflict. This is common when porting SVGs from web contexts where `<img>` tags prevent ID 'leakage'.
- gotcha TypeScript projects require a declaration file (`declarations.d.ts` or similar) to properly type SVG imports, otherwise, TypeScript will report errors for unknown module types.
Install
-
npm install react-native-svg-transformer -
yarn add react-native-svg-transformer -
pnpm add react-native-svg-transformer
Imports
- SVG as Component
import Logo from "./assets/logo.svg?url"; // Common mistake in some bundlers import { SvgXml } from 'react-native-svg'; // For XML strings, not direct file importimport Logo from "./assets/logo.svg"; // ... <Logo width={100} height={100} fill="blue" /> - Metro Config Path (Bare React Native)
babelTransformerPath: require.resolve("react-native-svg-transformer")babelTransformerPath: require.resolve("react-native-svg-transformer/react-native") - Metro Config Path (Expo)
babelTransformerPath: require.resolve("react-native-svg-transformer/react-native")babelTransformerPath: require.resolve("react-native-svg-transformer/expo")
Quickstart
npm install --save-dev react-native-svg-transformer
npm install react-native-svg
cd ios && pod install # For iOS projects
// metro.config.js (for React Native v0.72.1 or newer)
const { getDefaultConfig, mergeConfig } = require("@react-native/metro-config");
const defaultConfig = getDefaultConfig(__dirname);
const { assetExts, sourceExts } = defaultConfig.resolver;
const config = {
transformer: {
babelTransformerPath: require.resolve(
"react-native-svg-transformer/react-native"
)
},
resolver: {
assetExts: assetExts.filter((ext) => ext !== "svg"),
sourceExts: [...sourceExts, "svg"]
}
};
module.exports = mergeConfig(defaultConfig, config);
// App.js or any component file
import React from 'react';
import { View, StyleSheet } from 'react-native';
import Logo from './assets/logo.svg'; // Assuming logo.svg is in an assets folder
const App = () => {
return (
<View style={styles.container}>
<Logo width={200} height={200} fill="#FF6347" />
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
});
export default App;