I have an array of .svg
icons, where each icon has some properties which I need to override:
<svg width="24" height="24" viewBox="0 0 24 24"> ... </svg>
import styled from 'styled-components';
import Github from 'assets/github.svg';
import Facebook from 'assets/facebook.svg';
import Twitter from 'assets/twitter.svg';
...
const icons = [
<Github />,
<Facebook />,
<Twitter />,
...
];
I would like to apply the same styling for each icon without duplicating code and using CSS-in-JS
.
My solution so far has some issues:
// Works but,
// I want to use CSS-in-JS like styled-components
// for easier maintenance
const iconStyle = {
width: 50,
height: 50
};
const SocialBar = () => (
<IconBar as={FlexBox}>
{icons.map((icon, key) => (
<div key={key}>{React.cloneElement(icon, iconStyle)}</div>
))}
</IconBar>
);
// Works but,
// there are too many icons
const SocialBar = () => (
<IconBar as={FlexBox}>
<Github style={iconStyle} />
<Facebook style={iconStyle} />
...
</IconBar>
);
And styling svg
component like this won't work:
// Won't override the width="24" height="24" properties
const StyledIcon = styled(Github)`
width: 50;
height: 50;
`;
You can wrap the SVG with an element (like an i
) and style any svg
children inside of it with some CSS defined within a styled-component (you can also target g
and path
as well). Unfortunately, SVGs are pretty tricky to work with, so you may need to manually copy/paste the SVG xml into a JS file (if you're using the CRA , you can import a ReactComponent from an SVG ).
Working example (copy/pasted SVG into JS file -- 1st example is the default, 2nd example passes in props, 3rd example passes in multiple props):
Icon/Icon.js (this component accepts a styled component generated className
and any children
placed inside of it)
import React from "react";
import PropTypes from "prop-types";
const Icon = ({ className, children }) => (
<i className={className}>{children}</i>
);
Icon.propTypes = {
className: PropTypes.string.isRequired,
children: PropTypes.node.isRequired
};
export default Icon;
Icon/index.js (this will style the Icon
component above; and, subsequently it will style the children
)
import styled from "styled-components";
import Icon from "./Icon";
const StyledIcon = styled(Icon)`
margin: 0 20px;
svg {
fill: ${({ fill }) => fill || "#03a9f3"};
height: ${({ dimension }) => dimension || "50px"};
width: ${({ dimension }) => dimension || "50px"};
}
`;
export default StyledIcon;
This is one way of doing it.
//Github.js
import React from "react";
export default function Github({height, width}) {
return (
<svg width={width} height={height} viewBox="0 0 24 24"> ... </svg>
);
}
Then where you want to use it.
<Github height={24} width={24} />
I'm not entirely sure what your request is, relative to the code samples you already have. Are you trying to avoid using React.cloneElement
? Make the array of icons as functions, instead of a jsx element. map
over it to the jsx version and apply the styles to each
const icons = [
Github,
Facebook,
Twitter,
]
buildIcons() {
const style = {
//..
}
return icons.map((icon, idx) => (
<icon style={style} key={idx}/>
))
}
Using index as the key works, but if you can find a different property that is unique to each icon, it'd be better.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.