2

I'm using lot of svg images with the help of these two libraries

"react-native-svg": "^12.1.0",
"react-native-svg-transformer": "^0.14.3",

Then I can able to import and use svg images like below.

import Logo from '../assets/svg/img.svg';
...
...
<Logo height={60} />
...

The below is my custom button

***imaginary part // import Logo from '../assets/svg/img.svg';

const ButtonPressable = (props) => {
  return (
    <View>
      <Pressable
        style={[
          props.backgroundColor
            ? {backgroundColor: props.backgroundColor}
            : {backgroundColor: '#0077b6'},
        ]}>
        <Text>
          {props.text ? props.text : ''}
        </Text>

***imaginary part // <Logo height={60} />

      </Pressable>
    </View>
  );
};

I'm using above component like below

<ButtonPressable text="Login" backgroundColor="red" />

If you look at the imaginary part in above code. With that way, I can show svg images inside a component. But, I need to display svg images as a prop like below.

<ButtonPressable text="Login" backgroundColor="red" svg="../assets/svg/img.svg" />

How to pass svg path as a prop and display inside a component ?

  • If I understand correctly, you want to pass svg as a prop. Right now you are passing a path which won't work, instead, pass that ```imaginary part``` ie ```import Logo from '../assets/svg/img.svg';``` then pass Logo as svg prop to ``````. – Sameer Kumar Jain Sep 29 '20 at 06:30
  • @SaachiTech Anything is ok for me, currently I'm passing image as prop exactly as in below answer. But, That was not working for svg. Any work around is greatly welcome. –  Sep 29 '20 at 06:33
  • if you don't mind me asking why do you have to pass it as props when its a static content and not just use like you do in the imaginary part? – Glitch_Znab Sep 29 '20 at 06:41
  • @Glitch_Znab We create components to use in multiple projects. So, We cannot hard code anything in components. That's the main feature of react native If i'm right. –  Sep 29 '20 at 06:44
  • Ok. Have you tried converting SVG to JSX and passing? if not let me post an answer – Glitch_Znab Sep 29 '20 at 06:45
  • @Glitch_Znab never tried. But great idea –  Sep 29 '20 at 06:46

4 Answers4

3

Here is an example of how to pass SVG imported from the main component. The idea is ButtonPressable will have a prop, svg, it could be anything but it can be SVG as well. Please modify ButtonPressable as below

const ButtonPressable = (props) => {
  return (
    <View>
      <Pressable
        style={[
          props.backgroundColor
            ? {backgroundColor: props.backgroundColor}
            : {backgroundColor: '#0077b6'},
        ]}>
        <Text>
          {props.text ? props.text : ''}
        </Text>

{props.svg? <props.svg height={60} /> : null}

      </Pressable>
    </View>
  );
};

and then import them anywhere like this and pass SVG

import Logo from '../assets/svg/img.svg';
<ButtonPressable text="Login" backgroundColor="red" svg={Logo} />

This will keep ButtonPressable reusable.

Sameer Kumar Jain
  • 2,074
  • 1
  • 13
  • 22
  • 1
    This is perfectly working and this is what i'm looking - Dynamic component block creation. –  Sep 30 '20 at 05:52
2

There are multiple ways you could use SVG in your project,

  1. converting SVG to font files and importing them in your project. I haven't tried this as you will have to do this process every time you have to add one more icon.

  2. use react-native-svg-transformer, I have myself used this, and was easy to implement (though not tried in Expo). Documentation is clear on how to implement in the project.

And you can create 2 files,

  1. export all the svg's
import LeftArrowIcon from "@src/assets/svg/leftArrow.svg";

export const IconFiles = {
  LeftArrowIcon
};

export const IconNames = {
   LEFT_ARROW_ICON: "LeftArrowIcon", // value should as same as icon fileimport
};

  1. A single common component for Icons (based on svgs)
// icon.tsx
import { IconFiles } from "@src/themes/icons";

// props: {iconName: string} example: LEFT_ARROW_ICON
export default (props) => {
  const I = IconFiles[`${props.iconName}`];
  return (
    <I width={defaultWidth || fromProps} height={defaultHeight || fromProps} />
  );
};

And eventually in your ButtonComponent,

const ButtonPressable = (props) => {
  return (
    <View>
      <Pressable
        style={[
          props.backgroundColor
            ? {backgroundColor: props.backgroundColor}
            : {backgroundColor: '#0077b6'},
        ]}>
        <Text>
          {props.text ? props.text : ''}
        </Text>
       <Icon iconName={props.iconName} />
      </Pressable>
    </View>
  );
};

And in your parent component, you could use it like,

<ButtonPressable 
  text="Login" 
  backgroundColor="red" 
  iconName={IconNames.LEFT_ARROW_ICON} 
/>
senthil balaji
  • 588
  • 4
  • 18
1

Convert your SVG to JSX. you can then use that as an icon component.

you can use this SVG 2 JSX or SVGR Playground

For example below is a left arrow svg.

<svg xmlns="http://www.w3.org/2000/svg" width="20" height="16.327" viewBox="0 0 20 16.327"><path d="M-9.974-7.735a.988.988,0,0,0,.334.722L-2.489.127a.982.982,0,0,0,.7.3A.918.918,0,0,0-.841-.5a.943.943,0,0,0-.269-.679L-3.523-3.631l-3.63-3.306,2.606.162H9.078a.913.913,0,0,0,.948-.959.913.913,0,0,0-.948-.959H-4.546l-2.6.162,3.619-3.306,2.412-2.456a.961.961,0,0,0,.269-.679.918.918,0,0,0-.948-.926.964.964,0,0,0-.722.323L-9.64-8.456A.988.988,0,0,0-9.974-7.735Z" transform="translate(9.974 15.898)"/></svg>

then you can use the above link and covert it to a JSX.

import * as React from 'react';
import Svg, { Path } from 'react-native-svg';

export interface IconLeftArrowProps {
  width?: number;
  height?: number;
  color?: string;
}

/**
 * IconLeftArrow
 * Base svg file
 * assets/images/svgsSrc/icon_arrow_left.svg
 * @param
 * width   {Number} [ svg width size,  default size 20 ]
 * height  {Number} [ svg height size, default size 16.327 ]
 * color   {String} [ svg fill color,  default color BLACK(#000000) ]
 */
const IconLeftArrow: React.FC<IconLeftArrowProps> = ({
  width = 20 ,
  height = 16.327 ,
  color = #000000,
}) => (
  <Svg width={width} height={height} viewBox="0 0 20 16.327">
    <Path
      fill={color}
      d="M-9.974-7.735a.988.988,0,0,0,.334.722L-2.489.127a.982.982,0,0,0,.7.3A.918.918,0,0,0-.841-.5a.943.943,0,0,0-.269-.679L-3.523-3.631l-3.63-3.306,2.606.162H9.078a.913.913,0,0,0,.948-.959.913.913,0,0,0-.948-.959H-4.546l-2.6.162,3.619-3.306,2.412-2.456a.961.961,0,0,0,.269-.679.918.918,0,0,0-.948-.926.964.964,0,0,0-.722.323L-9.64-8.456A.988.988,0,0,0-9.974-7.735Z"
      transform="translate(9.974 15.898)"
    />
  </Svg>
);

export default IconLeftArrow;

I can't say for sure that the converters work perfectly as I also have faced issues. But if it does not work try to Change svg to Svg, path to Path and so on.

Then you can just import them and use them.

Glitch_Znab
  • 496
  • 4
  • 13
  • This is little complicated. If there is a way to generate component dynamically including imports. Then it could be easier to inject import and its usage statements directly into desired line in our custom component. Anyhow I'll try this and check if nothing works. –  Sep 29 '20 at 06:51
  • Actually it looks complicated because of the typescript but you can just copy the above code everywhere and replace only the Svg content i.e. with svg code. – Glitch_Znab Sep 29 '20 at 06:56
0

How about you do that?

<img src={require(props.svg)} alt="Logo" height={60} />
Osama Sayed
  • 1,993
  • 15
  • 15
  • This will not give any error and works for only images but, It just doesn't work for svg. Kindly refer this https://github.com/kristerkari/react-native-svg-transformer we must use it like they mentioned. –  Sep 29 '20 at 06:05