Как применить стиль к массиву элементов SVG

У меня есть массив значков .svg, где у каждого значка есть некоторые свойства, которые мне нужно переопределить:

<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 />,
  ...
];

Я хотел бы применить один и тот же стиль для каждой иконки без дублирования кода и использовать CSS-in-JS.

Мое решение до сих пор имеет некоторые проблемы:

// 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>
);

И такой стиль компонента svg не будет работать:

// Won't override the width = "24" height = "24" properties
const StyledIcon = styled(Github)`
  width: 50;
  height: 50;
`;
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
1 239
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Это один из способов сделать это.

//Github.js
import React from "react";
export default function Github({height, width}) {
    return (
        <svg width = {width} height = {height} viewBox = "0 0 24 24"> ...  </svg>
    );
}

Затем, где вы хотите его использовать.

<Github height = {24} width = {24} />

Как это помогает? Как я могу применить его к массиву значков? Это похоже на применение встроенного стиля, поэтому мне нужно создать функцию для каждой иконки.

Dennis Vash 19.07.2019 01:59

Я не совсем уверен, каков ваш запрос относительно уже имеющихся у вас примеров кода. Вы пытаетесь избежать использования React.cloneElement? Сделайте массив значков функциями, а не элементом jsx. map над ним в версию jsx и применить стили к каждому

const icons = [
  Github,
  Facebook,
  Twitter,
]

buildIcons() {
  const style = {
    //..
  }
  return icons.map((icon, idx) => (
    <icon style = {style} key = {idx}/>
  ))

}

Использование индекса в качестве ключа работает, но если вы можете найти другое свойство, уникальное для каждого значка, было бы лучше.

Я пытаюсь стилизовать каждую иконку с помощью css-in-js, и, кстати, ваш код не будет работать, потому что icon должен быть в верхнем регистре, иначе реакция не распознает его.

Dennis Vash 19.07.2019 11:50

Ну вот так? cssinjs.org/?v=v10.0.0-alpha.22 Похоже, у jss есть несколько доступных вам HOC

Andrew 19.07.2019 20:28
Ответ принят как подходящий

Вы можете обернуть SVG элементом (например, i) и стилизовать любые дочерние элементы svg внутри него с помощью некоторого CSS, определенного внутри styled-component (вы также можете настроить таргетинг на g и path). К сожалению, с SVG довольно сложно работать, поэтому вам мая нужно вручную скопировать/вставить SVG xml в файл JS (если вы используете КРА, вы можете импортировать ReactComponent из SVG).

Рабочий пример (скопируйте/вставьте SVG в файл JS - 1-й пример используется по умолчанию, 2-й пример проходит в реквизитах, 3-й пример проходит в нескольких реквизитах):

Edit Styled SVG Component


Значок/Icon.js (этот компонент принимает стилизованный компонент, сгенерированный className, и любой children, помещенный внутри него)

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;

Значок/index.js (это стилизует компонент Icon выше, а затем стилизует 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;

Другие вопросы по теме