Skip to content

Instantly share code, notes, and snippets.

@lukem512
Created May 12, 2017
Embed
What would you like to do?
Convert an SVG React component to React Native
/* @flow */
import React from 'react';
import Svg, {
Circle,
Ellipse,
G,
LinearGradient,
RadialGradient,
Line,
Path,
Polygon,
Polyline,
Rect,
Symbol,
Text,
Use,
Defs,
Stop,
} from 'react-native-svg';
const replacementMap = {
svg: Svg,
circle: Circle,
ellipse: Ellipse,
g: G,
linearGradient: LinearGradient,
radialGradient: RadialGradient,
line: Line,
path: Path,
polygon: Polygon,
polyline: Polyline,
rect: Rect,
symbol: Symbol,
text: Text,
use: Use,
defs: Defs,
stop: Stop,
};
const _replaceElement = function(tree, depth, child = 0) {
// Find the equivalent element to replace
const newElement = replacementMap[tree.type];
if (!newElement) {
return tree;
}
// Remove the width and height props from style and add them
// to the element directly.
const { children, style = {}, ...props } = tree.props;
const { width, height, ...newStyle } = style;
const newProps = {
...props,
...newStyle,
key: `svg.${depth}.${child}`,
// 'px' is not supported by react native
...(width && { width: width.replace('px', '') }),
...(height && { height: height.replace('px', '') }),
};
return React.createElement(newElement, newProps, replaceElement(children));
};
const replaceElement = function(tree, depth = 0) {
if (!tree) {
return null;
}
if (Array.isArray(tree)) {
return tree.map((el, child) => _replaceElement(el, depth + 1, child));
}
return _replaceElement(tree, depth + 1);
};
// Inheritance inversion is used to hijack the SVG rendering.
// The SVG elements are replaced with native equivalents.
export default function(WrappedComponent) {
return class Enhancer extends WrappedComponent {
render() {
const elementTree = super.render();
if (elementTree && elementTree.type === 'svg') {
const replaced = replaceElement(elementTree);
return replaced;
}
return null;
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment