software-mansion / react-native-svg

SVG library for React Native, React Native Web, and plain React web projects.
MIT License
7.5k stars 1.13k forks source link

replace error on xml source after upgrading to React Native 0.75 #2458

Closed IncrediblePony closed 3 weeks ago

IncrediblePony commented 1 month ago

Description

I have this xml representing an svg:

<?xml version="1.0" encoding="iso-8859-1"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#000000" version="1.1" id="Capa_1" width="800px" height="800px" viewBox="0 0 495.398 495.398" xml:space="preserve"><g><g><g><path d="M487.083,225.514l-75.08-75.08V63.704c0-15.682-12.708-28.391-28.413-28.391c-15.669,0-28.377,12.709-28.377,28.391     v29.941L299.31,37.74c-27.639-27.624-75.694-27.575-103.27,0.05L8.312,225.514c-11.082,11.104-11.082,29.071,0,40.158     c11.087,11.101,29.089,11.101,40.172,0l187.71-187.729c6.115-6.083,16.893-6.083,22.976-0.018l187.742,187.747     c5.567,5.551,12.825,8.312,20.081,8.312c7.271,0,14.541-2.764,20.091-8.312C498.17,254.586,498.17,236.619,487.083,225.514z"/><path d="M257.561,131.836c-5.454-5.451-14.285-5.451-19.723,0L72.712,296.913c-2.607,2.606-4.085,6.164-4.085,9.877v120.401     c0,28.253,22.908,51.16,51.16,51.16h81.754v-126.61h92.299v126.61h81.755c28.251,0,51.159-22.907,51.159-51.159V306.79     c0-3.713-1.465-7.271-4.085-9.877L257.561,131.836z"/></g></g></g></svg>

This is the unformatted xml sent from my provider, which my react-native application receives:

"<?xml version=\"1.0\" encoding=\"iso-8859-1\"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools --><!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"><svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" fill=\"#000000\" version=\"1.1\" id=\"Capa_1\" width=\"800px\" height=\"800px\" viewBox=\"0 0 495.398 495.398\" xml:space=\"preserve\">
<g>
        <g>
                <g>
                        <path d=\"M487.083,225.514l-75.08-75.08V63.704c0-15.682-12.708-28.391-28.413-28.391c-15.669,0-28.377,12.709-28.377,28.391     v29.941L299.31,37.74c-27.639-27.624-75.694-27.575-103.27,0.05L8.312,225.514c-11.082,11.104-11.082,29.071,0,40.158     c11.087,11.101,29.089,11.101,40.172,0l187.71-187.729c6.115-6.083,16.893-6.083,22.976-0.018l187.742,187.747     c5.567,5.551,12.825,8.312,20.081,8.312c7.271,0,14.541-2.764,20.091-8.312C498.17,254.586,498.17,236.619,487.083,225.514z\"/>
                        <path d=\"M257.561,131.836c-5.454-5.451-14.285-5.451-19.723,0L72.712,296.913c-2.607,2.606-4.085,6.164-4.085,9.877v120.401     c0,28.253,22.908,51.16,51.16,51.16h81.754v-126.61h92.299v126.61h81.755c28.251,0,51.159-22.907,51.159-51.159V306.79     c0-3.713-1.465-7.271-4.085-9.877L257.561,131.836z\"/>
                </g>
        </g>
</g>
</svg>"

The minified svg icon renders as intended in online svg tools. The "raw" svg icon doesn't. When attempting to load the icon from the xml I get this errormessage:

ERROR: TypeError: An error was thrown when attempting to render log messages via LogBox.

args[0].replace is not a function (it is undefined), js engine: hermes 
    at SvgXml (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=com.glfr&modulesOnly=false&runModule=true:430621:31)

The error is thrown here: node_modules/react-native-svg/src/xml.tsx in function SvgXml on line 77.

export function SvgXml(props: XmlProps) {
  const { onError = err, xml, override, fallback } = props;

  try {
    const ast = useMemo<JsxAST | null>(
      () => (xml !== null ? parse(xml) : null),
      [xml]
    );
    return <SvgAst ast={ast} override={override || props} />;
  } catch (error) {
    onError(error);
    return fallback ?? null;
  }
}

Why would this issue occur?

Steps to reproduce

  1. Make an xml file with the raw xml/svg presented in the description
  2. Attempt to render it with <SvgXml />
import { SvgFromXml, SvgXml } from 'react-native-svg'

export const QuickLinkItemView = ({ name, unhandledUrl, icon, clubId }: QuickLinkProps) => {

  return (
    <View>
      <SvgXml xml={/* iconxml */} width={30} height={30} fill={'black'} />
    </View>
  )
}

Snack or a link to a repository

Snack

SVG version

15.7.1

React Native version

0.75.3

Platforms

Android

JavaScript runtime

Hermes

Workflow

React Native

Architecture

Fabric (New Architecture)

Build type

Debug app & dev bundle

Device

Android emulator

Device model

No response

Acknowledgements

Yes

IncrediblePony commented 1 month ago

https://snack.expo.dev/Rl2Jqv8kyotpma0onZCAO

jakex7 commented 1 month ago

Hi @IncrediblePony, Your SVG has escaped double quotes, \" which makes it invalid. You can validate the SVG string and check if it should render properly using this tool: https://validator.w3.org/#validate_by_input. react-native-svg has nothing to do here, as it's clearly not a valid xml. As a workaround, you should probably fetch the svg by yourself and just .replaceAll(`\"`, `"`) to fix the quotes before passing it to the SvgXml.

IncrediblePony commented 1 month ago

image

The funny thing is that this calendar icon:

<?xml version=\"1.0\" encoding=\"iso-8859-1\"?><svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" id=\"Capa_1\" x=\"0px\" y=\"0px\" viewBox=\"0 0 489.2 489.2\" style=\"enable-background:new 0 0 489.2 489.2;\" xml:space=\"preserve\"><g><g><path d=\"M177.8,238.1c0,4.5-3.6,8.1-8.1,8.1h-30.4c-4.5,0-8.1-3.6-8.1-8.1v-30.4c0-4.5,3.6-8.1,8.1-8.1h30.4    c4.5,0,8.1,3.6,8.1,8.1V238.1z M241.3,207.8c0-4.5-3.6-8.1-8.1-8.1h-30.4c-4.5,0-8.1,3.6-8.1,8.1v30.4c0,4.5,3.6,8.1,8.1,8.1h30.4    c4.5,0,8.1-3.6,8.1-8.1V207.8z M304.8,207.8c0-4.5-3.6-8.1-8.1-8.1h-30.4c-4.5,0-8.1,3.6-8.1,8.1v30.4c0,4.5,3.6,8.1,8.1,8.1h30.4    c4.5,0,8.1-3.6,8.1-8.1V207.8z M177.8,269.6c0-4.5-3.6-8.1-8.1-8.1h-30.4c-4.5,0-8.1,3.6-8.1,8.1V300c0,4.5,3.6,8.1,8.1,8.1h30.4    c4.5,0,8.1-3.6,8.1-8.1V269.6z M241.3,269.6c0-4.5-3.6-8.1-8.1-8.1h-30.4c-4.5,0-8.1,3.6-8.1,8.1V300c0,4.5,3.6,8.1,8.1,8.1h30.4    c4.5,0,8.1-3.6,8.1-8.1V269.6z M296.7,261.5h-30.4c-4.5,0-8.1,3.6-8.1,8.1V300c0,4.5,3.6,8.1,8.1,8.1h30.4c4.5,0,8.1-3.6,8.1-8.1    v-30.4C304.8,265.1,301.2,261.5,296.7,261.5z M106.1,323.3H75.8c-4.5,0-8.1,3.6-8.1,8.1v30.4c0,4.5,3.6,8.1,8.1,8.1h30.4    c4.5,0,8.1-3.6,8.1-8.1v-30.4C114.3,326.9,110.6,323.3,106.1,323.3z M114.3,269.6c0-4.5-3.6-8.1-8.1-8.1H75.8    c-4.5,0-8.1,3.6-8.1,8.1V300c0,4.5,3.6,8.1,8.1,8.1h30.4c4.5,0,8.1-3.6,8.1-8.1V269.6z M233.2,323.3h-30.4c-4.5,0-8.1,3.6-8.1,8.1    v30.4c0,4.5,3.6,8.1,8.1,8.1h30.4c4.5,0,8.1-3.6,8.1-8.1v-30.4C241.3,326.9,237.7,323.3,233.2,323.3z M169.7,323.3h-30.4    c-4.5,0-8.1,3.6-8.1,8.1v30.4c0,4.5,3.6,8.1,8.1,8.1h30.4c4.5,0,8.1-3.6,8.1-8.1v-30.4C177.8,326.9,174.2,323.3,169.7,323.3z     M360.2,246.3c4.5,0,8.1-3.6,8.1-8.1v-30.4c0-4.5-3.6-8.1-8.1-8.1h-30.4c-4.5,0-8.1,3.6-8.1,8.1v30.4c0,4.5,3.6,8.1,8.1,8.1H360.2    z M47.7,435.9h230.7c-3.7-11.6-5.8-24-5.9-36.8H47.7c-6,0-10.8-4.9-10.8-10.8V171h361.7v101.1c12.8,0.1,25.2,2,36.8,5.7V94.9    c0-26.3-21.4-47.7-47.7-47.7h-53.4V17.8c0-9.6-7.8-17.4-17.4-17.4h-27.1c-9.6,0-17.4,7.8-17.4,17.4v29.5H163V17.8    c0-9.6-7.8-17.4-17.4-17.4h-27.1c-9.6,0-17.4,7.8-17.4,17.4v29.5H47.7C21.4,47.3,0,68.7,0,95v293.3C0,414.5,21.4,435.9,47.7,435.9    z M489.2,397.7c0,50.3-40.8,91.1-91.1,91.1S307,448,307,397.7s40.8-91.1,91.1-91.1S489.2,347.4,489.2,397.7z M444.1,374.1    c0-2.9-1.1-5.7-3.2-7.7c-4.3-4.3-11.2-4.3-15.5,0L385.8,406l-15.2-15.2c-4.3-4.3-11.2-4.3-15.5,0c-2.1,2.1-3.2,4.8-3.2,7.7    c0,2.9,1.1,5.7,3.2,7.7l22.9,22.9c4.3,4.3,11.2,4.3,15.5,0l47.3-47.3C443,379.8,444.1,377,444.1,374.1z\"/></g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g></svg>

This icon renders perfectly fine (as shown on screendump). Same goes for the knife and spoon icon:

<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"48px\" viewBox=\"0 0 24 24\" width=\"48px\" fill=\"#000000\"><path d=\"M0 0h24v24H0z\" fill=\"none\"/><path d=\"M8.1 13.34l2.83-2.83L3.91 3.5c-1.56 1.56-1.56 4.09 0 5.66l4.19 4.18zm6.78-1.81c1.53.71 3.68.21 5.27-1.38 1.91-1.91 2.28-4.65.81-6.12-1.46-1.46-4.2-1.1-6.12.81-1.59 1.59-2.09 3.74-1.38 5.27L3.7 19.87l1.41 1.41L12 14.41l6.88 6.88 1.41-1.41L13.41 13l1.47-1.47z\"/></svg>

The only problem is with the "Home" icon as described in the issue. All of them comes from the same source (our own icon library in from our database). So I don't really see that this should be the issue.

Either way, why would the code fail outright? Why not just a warning instead of a full on error, which breaks running code?

bohdanprog commented 1 month ago

@IncrediblePony can you try to run that with onError props and check what will be inside? <SvgXml xml={/* iconxml */} onError={(err) => console.log(err)} width={30} height={30} fill={'black'} />

IncrediblePony commented 1 month ago
function removeBackslashes(input: string): string {
  return input.replaceAll('\\"', '"')
}

<SvgXml
    xml={removeBackslashes(icon)}
    onError={err => console.log('Xml icon error -- ', err)}
    width={30}
    height={30}
    fill={'black'}
/>
 LOG  Xml icon error --  [TypeError: Cannot read property 'push' of null]
 LOG  Xml icon error --  [TypeError: Cannot convert null value to object]

This is the result.

The strange thing is that these issues were never a problem before I started to upgrade from 0.72 RN to 0.75

bohdanprog commented 1 month ago

@IncrediblePony I tried to reproduce that issue with those dependencies:

   "react": "18.3.1",
    "react-native": "0.75.1",

Would you be able to create a simple repo with that issue?

IncrediblePony commented 1 month ago

We might have been going down a wrong avenue here - the character escaped double qoutes are just a result of displaying a string in my terminal. I apologize. The component handles the escape characters just fine it would seem.

We ran the broken svg through the "optimizer" here: https://www.svgviewer.dev/

Broken svg:

<?xml version="1.0" encoding="iso-8859-1"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo
Mixer Tools -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#000000"
  version="1.1" id="Capa_1" width="800px" height="800px" viewBox="0 0 495.398 495.398"
  xml:space="preserve">
  <g>
    <g>
      <g>
        <path d= "M487.083,225.514l-75.08-75.08V63.704c0-15.682-12.708-28.391-28.413-28.391c-15.669,0-28.377,12.709-28.377,28.391     v29.941L299.31,37.74c-27.639-27.624-75.694-27.575-103.27,0.05L8.312,225.514c-11.082,11.104-11.082,29.071,0,40.158     c11.087,11.101,29.089,11.101,40.172,0l187.71-187.729c6.115-6.083,16.893-6.083,22.976-0.018l187.742,187.747     c5.567,5.551,12.825,8.312,20.081,8.312c7.271,0,14.541-2.764,20.091-8.312C498.17,254.586,498.17,236.619,487.083,225.514z" />
        <path d= "M257.561,131.836c-5.454-5.451-14.285-5.451-19.723,0L72.712,296.913c-2.607,2.606-4.085,6.164-4.085,9.877v120.401     c0,28.253,22.908,51.16,51.16,51.16h81.754v-126.61h92.299v126.61h81.755c28.251,0,51.159-22.907,51.159-51.159V306.79     c0-3.713-1.465-7.271-4.085-9.877L257.561,131.836z" />
      </g>
    </g>
  </g>
</svg>

"optimized" svg:

<svg xmlns="http://www.w3.org/2000/svg" width="800" height="800" viewBox="0 0 495.398 495.398"
  xml:space="preserve">
  <path d="m487.083 225.514-75.08-75.08v-86.73c0-15.682-12.708-28.391-28.413-28.391-15.669 0-28.377 12.709-28.377 28.391v29.941L299.31 37.74c-27.639-27.624-75.694-27.575-103.27.05L8.312 225.514c-11.082 11.104-11.082 29.071 0 40.158 11.087 11.101 29.089 11.101 40.172 0l187.71-187.729c6.115-6.083 16.893-6.083 22.976-.018l187.742 187.747a28.34 28.34 0 0 0 20.081 8.312c7.271 0 14.541-2.764 20.091-8.312 11.086-11.086 11.086-29.053-.001-40.158"/>
  <path d="M257.561 131.836c-5.454-5.451-14.285-5.451-19.723 0L72.712 296.913a13.98 13.98 0 0 0-4.085 9.877v120.401c0 28.253 22.908 51.16 51.16 51.16h81.754v-126.61h92.299v126.61h81.755c28.251 0 51.159-22.907 51.159-51.159V306.79c0-3.713-1.465-7.271-4.085-9.877z"/>
</svg>

The optimized svg works flawlessly. I'm currently trying to figure out why.

amerllica commented 1 month ago

I'm getting:

cannot read property SvgXml of undefined

react: 18.3.1 react-native: 0.75.3 react-native-svg: 13.14.0

Is my error related to this issue?

bohdanprog commented 1 month ago

@amerllica give us any examples, please.

IncrediblePony commented 1 month ago

@bohdanprog - alright. Your SVG Xml component is not able to handle and <!DOCTYPE> tags. Which is fair I'd say. The component doesn't seem to handle xml namespaces such as xmlns:xlink and xml:space as well. But it seems like it's mostly the doctype and xml tags which messes the svg's up.

amerllica commented 1 month ago

Dear @bohdanprog, by updating to 13.14.1 the issue got fixed.

bohdanprog commented 1 month ago

Dear @bohdanprog, by updating to 13.14.1 the issue got fixed.

Did you try to update to 15.7?

amerllica commented 1 month ago

No @bohdanprog, then my project needs to be updated and really it's so boring to me.