繁体   English   中英

将图标插入另一个组件的 React 方式是什么?

[英]What is the React way of inserting an icon into another component?

我正在尝试创建一个 WithIcon 包装器组件,它将一个子(图标)插入到包装的组件中。

假设我有一个按钮:

<Button>Add item</Button>

我想创建一个组件 WithIcon ,它将像这样使用:

<WithIcon i="plus"><Button>Add item</Button></WithIcon>

最终我想要实现的是:

<Button className="with-icon"><i className="me-2 bi bi-{icon}"></i>Add item</Button>

请注意添加的 className 和 Button 正文中的标记。

我试图弄清楚 WithIcon 组件的代码应该是什么样子。 实现此结果的 React 方法是什么?

最难的部分是使用WithIcon的规则 我们只有一个吗? 我们只会在最左边吗? 类似的东西。

但是,如果我们以您为榜样。 我们可以相对地为WithIcon写这样的东西

const WithIcon = ({ i, children }) => {
  return React.Children.map(children, (child) => {
    return (
      <>
        <i className={`me-2 bi bi-${i}`}></i>
        {React.cloneElement(child, { className: "with-icon" })}
      </>
    );
  });
};

然后我们可以按照您想要的方式使用它

<WithIcon i="plus"><Button>Add item</Button></WithIcon>

我们所做的只是循环遍历子节点,这些子节点的反应是您放入其中的任何嵌套 jsx(在我们的例子中为按钮)

你可以在这里找到我的小提琴: https://codesandbox.io/s/react-font-awesome-forked-321tz?file=/src/index.js

更新所以我之前的回答并不完全符合我们想要的最终结果。 遗嘱必须是主要父母

这个想法还是和之前一样,但是这里我们在推断我们在 WithIcon 中传递的组件的类型 这也增加了当我们在WithIcon中传递嵌套组件时的保护措施

const WithIcon = ({ i, children }) => {
  return React.Children.map(children, (child) => {
    const MyType = child.type; // So we can get the Button
    return (
      <MyType className="with-icon">
        <i className={`me-2 bi bi-${i}`}></i>
        {(React.cloneElement(child, {}), [child.props.children])}
      </MyType>
    );
  });
};

我想我会 go 睡觉我会在以后更新解释的 rest。 在这里查看小提琴: https://codesandbox.io/s/react-font-awesome-forked-y43fx?file=/src/components/WithIcon.js

请注意,此代码不会保留传递组件的其他道具,但您可以通过在MyComponent中添加 {...child.props} 来相对添加它,这只是(反射之类?)推断组件。

当然也有像 HOC Enhancers 这样的另一种选择来执行此操作,但这会增加您如何声明组件 api 的复杂性。 所以选择最适合你的朋友

也许尝试使用更高阶的组件?

const withIcon = (icon, Component) => ({children, ...props}) => {
    return (
        <Component className="with-icon" {...props}>
            <i className=`me-2 bi bi-${icon}` /> 
            {children}
        </Component>
    );
}

那么用法是

const ButtonWithIcon = withIcon("your-icon", Button);

<ButtonWithIcon>Add Item</ButtonWithIcon>

根据我对反应的经验,它通常归结为使用组件内部的属性,例如此处( https://material-ui.com/api/button/ )或像我描述的那样的更高阶组件。

React 中使用了两种常见的模式来实现这种组合:

高阶组件

首先为您的按钮定义一个组件:

const Button = ({ className, children }) => (
  <button className={className}>{children}</button>
);

那么高阶组件可以这样实现:

const withIcon = (Component) => ({ i, className = '', children, ...props }) => (
  <Component {...props} className={`${className} with-icon`}>
    <i className={`me-2 bi bi-${i}`} />
    {children}
  </Component>
);

用法:

const ButtonWithIcon = withIcon(Button);

<ButtonWithIcon i="plus">Add Item</ButtonWithIcon>

语境

首先定义图标的上下文提供程序:

import { createContext } from 'react';

const Icon = createContext('');

const IconProvider = ({ i, children }) => (
  <Icon.Provider value={i}>{children}</Icon.Provider>
);

然后是你的组件:

import { useContext } from 'react';

const Button = ({ className = '', children }) => {
  const i = useContext(Icon);

  if (i) {
    className += ' with-icon';
    children = (
      <>
        <i className={`me-2 bi bi-${i}`} />
        {children}
      </>
    );
  }

  return (
    <button className={className}>{children}</button>
  );
};

用法:

<IconProvider i="plus"><Button>Add Item</Button></IconProvider>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM