react-native-svg icon indicating copy to clipboard operation
react-native-svg copied to clipboard

SvgUri example as given in README.md crashes in Expo Web

Open raarts opened this issue 2 years ago • 13 comments

Bug

I created a fresh expo app using expo init app-simple using the Typescript template. Added the SvgUri example. Resulted in the following error in my console:

(I have to add, the standard Expo <Image> component supports svg if you install react-native-svg. If not, it will skip svg files without warning.)

index.js:1 Warning: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Check the render method of `App`.
    at App
    at ExpoRootComponent (http://localhost:19007/static/js/bundle.js:8361:83)
    at div
    at http://localhost:19007/static/js/bundle.js:46754:25
    at div
    at http://localhost:19007/static/js/bundle.js:46754:25
    at AppContainer (http://localhost:19007/static/js/bundle.js:38675:24)
console.<computed> @ index.js:1
react-dom.development.js:25058 Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Check the render method of `App`.
    at createFiberFromTypeAndProps (react-dom.development.js:25058:1)
    at createFiberFromElement (react-dom.development.js:25086:1)
    at createChild (react-dom.development.js:13446:1)
    at reconcileChildrenArray (react-dom.development.js:13719:1)
    at reconcileChildFibers (react-dom.development.js:14125:1)
    at reconcileChildren (react-dom.development.js:16990:1)
    at updateHostComponent (react-dom.development.js:17632:1)
    at beginWork (react-dom.development.js:19080:1)
    at HTMLUnknownElement.callCallback (react-dom.development.js:3945:1)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:3994:1)
    at invokeGuardedCallback (react-dom.development.js:4056:1)
    at beginWork$1 (react-dom.development.js:23964:1)
    at performUnitOfWork (react-dom.development.js:22776:1)
    at workLoopSync (react-dom.development.js:22707:1)
    at renderRootSync (react-dom.development.js:22670:1)
    at performSyncWorkOnRoot (react-dom.development.js:22293:1)
    at scheduleUpdateOnFiber (react-dom.development.js:21881:1)
    at updateContainer (react-dom.development.js:25482:1)
    at react-dom.development.js:26021:1
    at unbatchedUpdates (react-dom.development.js:22431:1)
    at legacyRenderSubtreeIntoContainer (react-dom.development.js:26020:1)
    at render (react-dom.development.js:26103:1)
    at renderApplication (renderApplication.js:23:1)
    at Object.run (index.js:49:1)
    at Function.runApplication (index.js:93:1)
    at registerRootComponent (registerRootComponent.tsx:14:1)
    at Module../node_modules/expo/AppEntry.js (AppEntry.js:5:1)
    at __webpack_require__ (bootstrap:789:1)
    at fn (bootstrap:100:1)
    at Object.1 (tracing.js:7:1)
    at __webpack_require__ (bootstrap:789:1)
    at bootstrap:856:1
    at bootstrap:856:1

Environment info

Run react-native info in your terminal and copy the results here. Also, include the precise version number of this library that you are using in the project

React native info output:

System:
    OS: macOS 12.3.1
    CPU: (10) arm64 Apple M1 Pro
    Memory: 387.34 MB / 32.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 16.14.0 - /opt/homebrew/opt/node@16/bin/node
    Yarn: 1.22.17 - /opt/homebrew/bin/yarn
    npm: 8.3.1 - /opt/homebrew/opt/node@16/bin/npm
    Watchman: 2022.02.21.00 - /opt/homebrew/bin/watchman
  Managers:
    CocoaPods: 1.11.2 - /opt/homebrew/bin/pod
  SDKs:
    iOS SDK:
      Platforms: DriverKit 21.4, iOS 15.4, macOS 12.3, tvOS 15.4, watchOS 8.5
    Android SDK: Not Found
  IDEs:
    Android Studio: 2021.1 AI-211.7628.21.2111.8193401
    Xcode: 13.3/13E113 - /usr/bin/xcodebuild
  Languages:
    Java: 17.0.2 - /usr/bin/javac
  npmPackages:
    @react-native-community/cli: Not Found
    react: 17.0.1 => 17.0.1
    react-native: 0.64.3 => 0.64.3
    react-native-macos: Not Found
  npmGlobalPackages:
    *react-native*: Not Found

Library version: 12.1.1 (preferred by expo install, but same thing happend with 12.3.0)

Steps To Reproduce

Issues without reproduction steps or code are likely to stall.

  1. expo init app-simple (use typescript template)
  2. cd app-simple
  3. yarn add react-native-svg
  4. copy the example code for SvgUri into App.tsx
export default function App() {
  return (
    <View style={styles.container}>
      <Text>Open up App.tsx to start working on your app!</Text>
      <SvgUri
          // style={styles.image}
          width="100%"
          height="100%"
          uri="http://thenewcode.com/assets/images/thumbnails/homer-simpson.svg"
      />
      <StatusBar style="auto" />
    </View>
  );
}

Describe what you expected to happen:

I was expecting the app to show Homer. But it crashed and showed the above error instead.

raarts avatar Apr 09 '22 10:04 raarts

I have the same issue. Took forever to track here.

@raarts Have you found any workaround?

And can you explain what you mean by: I have to add, the standard Expo component supports svg if you install react-native-svg. If not, it will skip svg files without warning.

ansmlc avatar Apr 18 '22 00:04 ansmlc

I tried to show a list of remote images using FlatList and the Image component. This worked, except for the svg images. To Solve this I tried to detect (by file extension) what the image type was, and use the appropriate component to display the image. That's when I found out about the crashing.

Later on I found out that if react-native-svg is installed the Image component will support svg. So, that's what I ended up doing.

raarts avatar Apr 18 '22 07:04 raarts

I tried to show a list of remote images using FlatList and the Image component. This worked, except for the svg images. To Solve this I tried to detect (by file extension) what the image type was, and use the appropriate component to display the image. That's when I found out about the crashing.

Later on I found out that if react-native-svg is installed the Image component will support svg. So, that's what I ended up doing.

I have react-native-svg installed but Image component still doesn't render svg images.

Did you still have to import { Svg } from 'react-native-svg';?

This is my Image component:

                    <Image
                        source={{
                        uri: icon,
                        }}
                    /

Any idea why it's not working?

ansmlc avatar Apr 18 '22 11:04 ansmlc

No, I have no idea why it's not working, but are you sure you use uri properly? Mine is a http:// URL.

raarts avatar Apr 18 '22 14:04 raarts

No, I have no idea why it's not working, but are you sure you use uri properly? Mine is a http:// URL.

Mine is https:// URL.

Yes, it's corrent, I can see the SVG in DevTools inspect, when viewing in Expo Web:

<img alt="" draggable="false" src="https://res.cloudinary.com/dresqigku/image/upload/v1650007219/general_6d3491bccd.svg" class="css-accessibilityImage-9pa8cd">

There's no error, it just doesn't show anything.

When viewing in Expo iOS, it gives console warning: "Failed prop type: Invalid prop 'source' supplied to 'Image', expected one of type [number, number].

Are you sure all you had to do is install react-native-svg for Image component to be able to accept SVG?

ansmlc avatar Apr 19 '22 01:04 ansmlc

This is how I do it:

        <Image
          style={styles.image}
          source={{ uri: API_SERVER_URL + `/v1/s3/download?id=${item.id}` }}
          resizeMode="contain"
        />

I'm pretty sure I only needed to install react-native-svg. Maybe the remote server needs to send the 'Content-Type': 'image/svg+xml' ? Mine does.

raarts avatar Apr 20 '22 12:04 raarts

Hi everyone, any idea when it is going to be fixed? Using Image works for me on the web, but not on iOS (have not tried Android)

grzabrodskiy avatar Apr 21 '22 19:04 grzabrodskiy

I have the same bug. The only solution to display SVGs is either to use react-native Image, or if you wish to have your svg properly rendered to <svg> and stylable use Svg, Path, .. and construct it yourself. I guess that could be automated, but still a pain :/

Akronae avatar Jan 12 '23 10:01 Akronae

Same issues here, anybody making progress on this?

tmountain avatar Jun 08 '23 16:06 tmountain

Same issue here.

ritute avatar Jun 14 '23 21:06 ritute

Same issues here, anybody making progress on this?

airowe avatar Mar 13 '24 17:03 airowe

Same issue

Bi0max avatar Mar 27 '24 19:03 Bi0max

SvgUri does not seem to be implemented/supported for the web.

Here is a very quick fix that I have hacked together. There is probably a better way to do it.

Inside of node_modules/react-native-svg/lib/module/ReactNativeSVG.web.js or node_modules/react-native-svg/lib/commonjs/ReactNativeSVG.web.js (depending on which module you are using) add this:

export async function fetchText(uri) {
  const response = await fetch(uri);
  if (response.ok || response.status === 0 && uri.startsWith('file://')) {
    return await response.text();
  }
  throw new Error(`Fetching ${uri} failed with status ${response.status}`);
}
export function SvgUri(props) {
  const { onError, uri, onLoad, fallback } = props;
  const [xml, setXml] = React.useState(null);
  const [isError, setIsError] = React.useState(false);
  React.useEffect(() => {
    uri
      ? fetchText(uri)
          .then((data) => {
            setXml(data);
            isError && setIsError(false);
            onLoad?.();
          })
          .catch((e) => {
            onError(e);
            setIsError(true);
          })
      : setXml(null);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [onError, uri, onLoad]);
  if (isError) {
    return fallback ?? null;
  }
  if (!xml) {
      return fallback ?? null;
  }
  const encoded = encodeSvg(xml);
  return createElement("img", { src: "data:image/svg+xml," + encoded });
}

I have placed it after the function measureLayout at the line 160, but it should work elsewhere.

You should save your patch with patch-package afterwards.

xavierhamel avatar Jul 04 '24 22:07 xavierhamel

Hello @airowe @raarts @tmountain, It should work now. But if you are still having that problem, please don't hesitate to let us know. here is an example of how you can check that problem:

import {View, Text} from 'react-native';
import {SvgUri} from 'react-native-svg';

export default function App() {
  return (
    <View style={{flex: 1, backgroundColor: 'purple'}}>
      <Text>Open up App.tsx to start working on your app!</Text>
      <SvgUri
        width="100%"
        height="100%"
        uri="https://upload.wikimedia.org/wikipedia/commons/7/73/Ruby_logo.svg"
      />
    </View>
  );
}

Thank you.

bohdanprog avatar Aug 27 '24 06:08 bohdanprog