skip to Main Content

I’m trying to dynamically import local SVG files with Suspense and lazy in React Native (v0.72.3). But I’m getting this error:

ERROR  [Error: TransformError Utils/DynamicSvg.tsx: Utils/DynamicSvg.tsx:Invalid call at line 13: import(url)]
Error: Utils/DynamicSvg.tsx:Invalid call at line 13: import(url)
    at transformJS (/Users/me/projects/myproj/node_modules/metro-transform-worker/src/index.js:225:15)
    at transformJSWithBabel (/Users/me/projects/myproj/node_modules/metro-transform-worker/src/index.js:343:16)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Object.transform (/Users/me/projects/myproj/node_modules/metro-transform-worker/src/index.js:461:12)

Here is my code:

import { Suspense, lazy } from 'react';
import { View } from 'react-native';

export const DynamicSvg = ({name}: any) => {
  
  console.log("name: " + name);
  const LazySvg = lazy(() => {
    const url = `./../assets/people/${name}`;
    
    return import(url);
  });

  return (
    <Suspense>
      <LazySvg />
    </Suspense>
  );
};

What am I doing wrong here and how can I fix it?

2

Answers


  1. The React Native doesn’t support SVG syntax or file directly. So to fix this you must follow the installation guide:

    1. Install react-native-svg
    2. Install react-native-svg-transformer.

    Then inside your project components, you can write like the following:

    import { View } from 'react-native';
    import YourSvgFile from './assets/svg/yourSvgFile.svg';
    
    const TheComponent = () => {
      return (
        <View>
          <YourSvgFile />
        </View>
      );
    };
    

    It does work, if you need to make a dynamic one, you should pre-import them and write like the following:

    import React from 'react';
    import { View } from 'react-native';
    import HomeIcon from '../icons/home.svg';
    import ShopIcon from '../icons/shop.svg';
    import SearchIcon from '../icons/search.svg';
    
    const IconMap = {
      home: HomeIcon,
      shop: ShopIcon,
      search: SearchIcon,
    } as const;
    
    type IconMapNamesType = keyof typeof IconMap;
    
    interface DynamicSvgProps {
      name: IconMapNamesType;
    }
    
    const DynamicSvg: React.FC<DynamicSvgProps> = ({ name }) => {
      const Icon = IconMap[name];
    
      if(!Icon) {
        return null;
      }
    
      return (
        <View>
          <Icon />
        </View>
      );
    };
    
    Login or Signup to reply.
  2. The error you’re encountering is due to the fact that React Native’s import() function doesn’t support dynamic import of local assets. However, you can achieve dynamic import of local SVG files by using a workaround.

    Instead of using import() directly, you can create a custom function to handle dynamic imports. Here’s how you can modify your code:

    1. Create a new file, let’s say dynamicImport.ts, and add the following code:
    import { Platform, PermissionsAndroid } from 'react-native';
    
    const dynamicImport = async (path: string) => {
      return new Promise((resolve, reject) => {
        const importModule = Platform.select({
          ios: () => import(`./${path}`),
          default: () =>
            PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE)
              .then(() => import(`./${path}`))
              .catch((err) => reject(err)),
        });
    
        importModule()
          .then((module) => resolve(module.default))
          .catch((err) => reject(err));
      });
    };
    
    export default dynamicImport;
    
    1. In your DynamicSvg component, import the dynamicImport function and use it to import the SVG file:
    import { Suspense, lazy } from 'react';
    import { View } from 'react-native';
    import dynamicImport from './dynamicImport';
    
    export const DynamicSvg = ({ name }: any) => {
      console.log("name: " + name);
      const LazySvg = lazy(() => dynamicImport(`../assets/people/${name}`));
    
      return (
        <Suspense>
          <LazySvg />
        </Suspense>
      );
    };
    

    This workaround uses the dynamicImport function to handle the dynamic import of local SVG files. It checks the platform (iOS or Android) and requests the necessary permissions (for Android) before importing the SVG file. Make sure to replace './dynamicImport' with the correct path to the dynamicImport.ts file in your project.

    Now, your DynamicSvg component should be able to import and render the SVG files dynamically.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search