react-native-svg: Very slow image loading

Question

Very slow image loading that slows down the app

Is there a better way to use <Image/>, because it’s very slow like that

Environment info

RN 0.61.4 react-native-svg 9.13.3

System: OS: macOS 10.15.2 CPU: (8) x64 Intel® Core™ i7-6700HQ CPU @ 2.60GHz Memory: 57.30 MB / 16.00 GB Shell: 5.7.1 - /bin/zsh Binaries: Node: 10.16.3 - /usr/local/bin/node Yarn: 1.19.1 - /usr/local/bin/yarn npm: 6.11.3 - /usr/local/bin/npm Watchman: 4.9.0 - /usr/local/bin/watchman SDKs: iOS SDK: Platforms: iOS 13.2, DriverKit 19.0, macOS 10.15, tvOS 13.2, watchOS 6.1 Android SDK: API Levels: 23, 26, 27, 28, 29 Build Tools: 27.0.3, 28.0.3, 29.0.2 System Images: android-29 | Google APIs Intel x86 Atom IDEs: Android Studio: 3.5 AI-191.8026.42.35.6010548 Xcode: 11.2.1/11B53 - /usr/bin/xcodebuild npmPackages: react: 16.9.0 => 16.9.0 react-native: 0.61.4 => 0.61.4 npmGlobalPackages: create-react-native-app: 2.0.2 react-native-cli: 2.0.1 react-native-debugger: 1.1.0

Steps To Reproduce

use this component with an image, worse if it’s in some kind of a list

Reproducible sample code


const SvgComponent = props => (
<Svg width="76px" height="76px" viewBox="0 0 76 76" version="1.1" {...props}>
    <Defs>
        <Path d="M8.17515049,11.5693781 C21.3484171,-1.60388046 47.1623186,-4.91796236 61.0399501,8.95966063 C74.918044,22.8377461 71.6039601,48.6516319 58.4306934,61.8248904 C45.2574268,74.998149 26.4362261,71.3195345 12.5581322,57.441449 C-1.3194993,43.563826 -4.99811612,24.7426367 8.17515049,11.5693781" id="path-3"></Path>
    </Defs>
    <G id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
        <G id="Avatar-/-S" transform="translate(-1.000000, 0.000000)">
            <G id="Avatar-/-Ombre">
                <Mask id="mask-2" fill="white">
                    <Use xlinkHref="#path-1"></Use>
                </Mask>
                <Use id="Fill-1" fill="#000000" fill-rule="evenodd" opacity="0.1" xlinkHref="#path-1"></Use>
            </G>
            <G id="Avatar" transform="translate(6.000000, 1.000000)">
                <Mask id="mask-4" fill="white">
                    <Use xlinkHref="#path-3"></Use>
                </Mask>
                <Use id="Fill-1" fill="#FFFFFF" xlinkHref="#path-3"></Use>
                <Image id="photo" mask="url(#mask-4)" x="-33.25" y="-3.5" width="136.5" height="75.25" xlinkHref={props.userImage}></Image>
            </G>
            <G id="Avatar-/-Statut-Off">
                <Path d="M14.1751505,12.5693781 C27.3484171,-0.603880461 53.1623186,-3.91796236 67.0399501,9.95966063 C80.918044,23.8377461 77.6039601,49.6516319 64.4306934,62.8248904 C51.2574268,75.998149 32.4362261,72.3195345 18.5581322,58.441449 C4.6805007,44.563826 1.00188388,25.7426367 14.1751505,12.5693781" id="Fill-1" stroke="#FF0000" stroke-width="2"></Path>
                <Path d="M14.9415748,13.2388245 C27.7384623,0.441944695 52.8148238,-2.77744915 66.2959515,10.7036703 C79.7775284,24.1852391 76.5581326,49.2615852 63.7612451,62.058465 C50.9643575,74.8553448 32.6809053,71.2818335 19.1993284,57.8002647 C5.71820068,44.3191452 2.1446872,26.0357042 14.9415748,13.2388245" id="Fill-1" stroke="#FFFFFF" stroke-width="1.94285714"></Path>
            </G>
        </G>
    </G>
</Svg>
)

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 16

Most upvoted comments

I’m seeing some flakyness, sometimes it doesn’t rerender after loading the image, when running the app from cold boot on ios. As soon as i open the dev tools (which seems strangely hung / nonresponsive to the cmd+d when this issue appears as well) it re-renders correctly. After refresh it renders correctly immediately. Seems I got it to work slightly better by using a onLoad handler on fastimage and forcing an update of the svg root like this:

babel.config.js

module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
  plugins: ['@babel/plugin-proposal-optional-chaining'],
};
import React, {useRef} from 'react';
import {View, Text} from 'react-native';
import {
  Svg,
  G,
  Circle,
  Defs,
  LinearGradient,
  Mask,
  Rect,
  Stop,
} from 'react-native-svg';
import FastImage from 'react-native-fast-image';

const YourImage = props => (
  <FastImage
    onLoad={props.onLoad}
    style={{width: 200, height: 200}}
    source={{
      uri: 'https://picsum.photos/200/200',
      priority: FastImage.priority.normal,
    }}
    resizeMode={FastImage.resizeMode.contain}
  />
);

export default () => {
  const svg = useRef(null);
  return (
    <View style={{flex: 1, justifyContent: 'center'}}>
      <Svg height="50%" ref={svg}>
        <Defs>
          <LinearGradient
            id="Gradient"
            gradientUnits="userSpaceOnUse"
            x1="0"
            y1="0"
            x2="800"
            y2="0">
            <Stop offset="0" stopColor="white" stopOpacity="0" />
            <Stop offset="1" stopColor="white" stopOpacity="1" />
          </LinearGradient>
          <Mask
            id="Mask"
            maskUnits="userSpaceOnUse"
            x="0"
            y="0"
            width="800"
            height="300">
            <Rect x="0" y="0" width="800" height="300" fill="url(#Gradient)" />
          </Mask>
        </Defs>
        <G mask="url(#Mask)">
          <Circle x={50} y={70} r={65} />
          <G transform="translate(50, 50)">
            <View>
              <YourImage
                onLoad={() => {
                  svg?.current?.forceUpdate?.();
                  console.log('onload');
                }}
              />
              <Text>Testing</Text>
              <Text>Testing2</Text>
            </View>
          </G>
        </G>
      </Svg>
    </View>
  );
};

Did you run pod install after adding fastimage?