Как изменить потомков данного свойства JSX.Element? - PullRequest
1 голос
/ 16 марта 2020

У меня есть следующий компонент:

import React, { ReactElement } from 'react'

interface Props {
  icon: JSX.Element; // should accept only svg
  fill?: string;
  stroke?: string;
}

export default function AppIcon(props: Props): ReactElement {
  // TODO:
  // Replace: svg *[fill] = props.fill
  // Replace: svg *[stroke] = props.stroke 
}

Как видите, компонент принимает значок JSX.Element (не уверен, как я могу ограничить его только SVG).

После этого он должен искать в дереве icon детей, имеющих атрибуты fill и stroke, и заменять их соответственно. Это означает, что если есть путь с fill, он заменит его на данную заливку. Если путь не имеет fill, он не будет добавлен.

Как мне добиться такого поведения?

1 Ответ

2 голосов
/ 18 марта 2020

Я думаю, мне удалось получить то, что вы хотите работать:

import React, { ReactElement } from "react";
import "./AppIcon.css";

interface Props {
    children: JSX.Element;
    fill?: string;
    stroke?: string;
}

export default function AppIcon(props: Props): ReactElement {
    return (
        // @ts-ignore
        <div className="AppIcon" style={{ "--fill": props.fill, "--stroke": props.stroke }}>
            {props.children}
        </div>
    );
}

В AppIcon.css:

.AppIcon > svg * {
    fill: var(--fill);
    stroke: var(--stroke);
}

Использование компонента:

...
<AppIcon fill="blue" stroke="yellow">
    <svg>
        <circle cx="50" cy="50" r="40" strokeWidth="3" />
    </svg>
</AppIcon>
...

Объяснение:

  • Во-первых, свойство icon в интерфейсе Props должно быть children. React заполнит это свойство любыми дочерними элементами компонента. Насколько я понимаю, нет способа ограничить это определенным именем тега, к сожалению.

  • Затем он переводит дочерний элемент в тег div. Здесь я даю тегу div имя_класса для идентификации позже, и я даю div стиль с двумя css пользовательскими свойствами , где их значения соответствуют заливке и обводке, предоставленным реквизитом. (TypeScript не нравится это, поскольку они не определены, поэтому у нас есть // @ts-ignore)

  • Эти свойства могут быть доступны любым потомкам / дочерним элементам элемента div. Таким образом, в соседней таблице стилей мы устанавливаем элементы в svg для использования переменных, установленных с ключевым словом var() в таблице стилей.

демо в кодахandbox

...