首页 > 解决方案 > 如何修改给定 JSX.Element 属性的子项?

问题描述

我有以下组件:

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的孩子并相应地替换。意思是,如果有一个带有 的路径,它将用给定的填充替换它。如果路径没有,则不会添加。fillstrokefillfill

我怎样才能实现这种行为?

标签: javascriptreactjssvgreact-tsx

解决方案


我想我已经设法得到你想要的工作:

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>
...

解释:

  • 首先iconProps 界面上的属性应该是children. React 将使用组件的任何子级填充该属性。据我了解,不幸的是,无法将其限制为某个标签名称。

  • 然后它在 div 标签下呈现孩子。在这里,我给那个div标签一个 className 以便稍后识别,我给 div 一个带有两个css 自定义属性的样式,它们的值与道具提供的填充和描边相匹配。(TypeScript 不喜欢这样,因为它们没有定义,所以我们有// @ts-ignore

  • div 元素的任何后代/子元素都可以访问这些属性。因此,在相邻的样式表中,我们将 svg 中的元素设置为使用var()样式表中的关键字设置的变量。

代码沙盒中的演示


推荐阅读