react-native-svg-transformer
react-native-svg-transformer copied to clipboard
InvalidCharacterError: String contains an invalid character
Hi,
Running a project with Expo, I am getting an InvalidCharacterError: String contains an invalid character
error on the web rendering. Android works fine and I haven't tested iOS.
I have the following dependencies in my package.json
:
{
...
"dependencies": {
"expo": "~37.0.3",
"react": "~16.9.0",
"react-dom": "~16.9.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-37.0.1.tar.gz",
"react-native-svg": "11.0.1",
"react-native-web": "~0.11.7"
},
"devDependencies": {
"@babel/core": "^7.8.6",
"babel-preset-expo": "~8.1.0",
"react-native-svg-transformer": "^0.14.3"
}
}
Here is my App.js
, the Bower SVG was taken from react-native-svg-example:
import React from 'react';
import { StyleSheet, View } from 'react-native';
import Bower from './assets/bower.svg';
export default function App() {
return (
<View style={styles.container}>
<Bower width={256} height={256} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Does anyone have an idea of what's going on?
Thanks
I have a similar error also on the web rendering
I'm getting the exact same behaviour, but with vanilla react-native/react-native-web. Works perfectly fine on iOS and Android, but not web. SVG file generated (e.g. /static/media/user.a61f6f35.svg
from above screenshot) exists and renders fine in Chrome.
I'm getting the exact same behaviour, but with vanilla react-native/react-native-web. Works perfectly fine on iOS and Android, but not web. SVG file generated (e.g.
/static/media/user.a61f6f35.svg
from above screenshot) exists and renders fine in Chrome.
Ok, so the problem is not related to Expo. Good to know, thanks!
I found a work around/fix. My file structure is:
/src
- /assets
-- /icons
--- /all-my-svg-files.svg
...
What I did was create 2 files, icons.ts
and icons.web.ts
under src/assets/icons
. In icons.ts
I had a list of entries such as import CloseSvg from "./close.svg"; export const Close = CloseSvg;
and in icons.web.ts
I had entries such as export { ReactComponent as Close } from "./close.svg";
.
Only issue now is that I obviously can't share the style
across both.
Hmm.. I'm guessing that Expo is using a different way of exporting/importing SVG images for their Web rendering.
Hmm.. I'm guessing that Expo is using a different way of exporting/importing SVG images for their Web rendering.
I don't think it is a problem related with Expo since @gigaSproule had the same problem with "vanilla react-native/react-native-web".
I saw made an example using Expo. I tried running it myself but I am getting the following error on web compilation.
/home/beetix/Tech/External/react-native-svg-expo-example/node_modules/react-native/Libraries/StyleSheet/processColor.js
Module not found: Can't resolve '../Utilities/Platform' in '/home/beetix/Tech/External/react-native-svg-expo-example/node_modules/react-native/Libraries/StyleSheet'
Do you remember if the web was rendering ok?
Yes, to clarify, I am not using expo.
@Beetix did you found a solution or some kind of workaround? Have the same problem
This transformer only seems to be used for Android and iOS.
For Web, I found that I needed the following webpack.config.js
:
const createExpoWebpackConfigAsync = require("@expo/webpack-config");
const { createAllLoaders } = require("@expo/webpack-config/loaders");
// Expo CLI will await this method so you can optionally return a promise.
module.exports = async (env, argv) => {
const config = await createExpoWebpackConfigAsync(env, argv);
config.module.rules = [
// Enable svgr in web build.
{
oneOf: [
{
test: /\.svg$/,
exclude: /node_modules/,
use: [
{
loader: "@svgr/webpack",
},
],
},
].concat(createAllLoaders(env)),
},
];
// Finally return the new config for the CLI to use.
return config;
};
For completeness, this is what I added to package.json
:
{
"dependencies": {
"react-native-svg": "^12.1.0"
},
"devDependencies": {
"@expo/webpack-config": "^0.12.40",
"@svgr/webpack": "^5.4.0",
"react-native-svg-transformer": "^0.14.3",
}
}
and for Android into metro.config.js
:
const { getDefaultConfig } = require("metro-config");
module.exports = (async () => {
const {
resolver: { sourceExts, assetExts },
} = await getDefaultConfig();
return {
transformer: {
babelTransformerPath: require.resolve("react-native-svg-transformer"),
},
resolver: {
assetExts: assetExts.filter((ext) => ext !== "svg"),
sourceExts: [...sourceExts, "svg"],
},
};
})();
I also have added the following to app.json
but have no idea if it is necessary:
{
"expo": {
"packagerOpts": {
"config": "metro.config.js",
"sourceExts": [
"expo.ts",
"expo.tsx",
"expo.js",
"expo.jsx",
"ts",
"tsx",
"js",
"jsx",
"json",
"wasm",
"svg"
]
}
}
}
For those using Expo, I suspect this is related to
https://github.com/expo/expo-cli/blob/164b4d5b193c8351cb11ccec3fe6f732478caa23/packages/webpack-config/src/loaders/createAllLoaders.ts#L42-L51
(there is even a todo for handling SVG better.)
It appears to me that, depending on how you implement the rule for @spgr/webpack
, ordering matters. You must unshift this rule to Expo's default set of oneOf
rules so it comes before the rule linked, above.