【问题标题】:Dynamically add a prop to Reactjs material ui Select为 Reactjs 材质 ui Select 动态添加一个 prop
【发布时间】:2020-04-21 07:38:34
【问题描述】:

我有一个关于材质 UI Select 组件以及如何动态设置 props 的问题。

我正在尝试将 Material UI Select (https://material-ui.com/components/selects/) 组件包装在我的 CompanySelect 中,以便添加一些额外的样式和其他内容。

主要问题

如何在材质 UI 选择组件上动态添加/删除 disableUnderline 属性。

当我设置 disableUnderline = null 和 variant = 'outlined' 时,我收到一条警告,指出 disableUnderline 是未知道具。使用 variant = 'standard' 时没有警告。

CompanySelect 组件代码

import React from 'react';
import Select from '@material-ui/core/Select';
import PropTypes from 'prop-types';
import ExpandMoreRoundedIcon from '@material-ui/icons/ExpandMoreRounded';
import './style.scss';

const CompanySelect= (props) => {
  const {
    variant,
    disableUnderline,
    children,
    ...
  } = props;

  return (
    <Select
      disableUnderline={disableUnderline}
      variant={variant}
      ...
    >
      {children}
    </Select>
  );
};

CompanySelect.propTypes = {
  variant: PropTypes.oneOf(['outlined', 'filled', 'standard']),
  disableUnderline: PropTypes.bool,
  children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired
};

CompanySelect.defaultProps = {
  variant: 'standard',
  disableUnderline: null,
};


export default CompanySelect;

标准用法

<AtriasSelect variant="standard" disableUnderline>
  <MenuItem />
  <MenuItem />
</AtriasSelect>

概述用法

<AtriasSelect variant="outlined">
  <MenuItem />
  <MenuItem />
</AtriasSelect>

标准用法有效。使用 disableUnderline 会删除默认下划线,如 Input API 页面上所述。 (https://material-ui.com/api/input/)。

当我使用概述的变体时会出现问题,因为 Select 继承了 OutlinedInput API。如果您查看 OutlinedInput API (https://material-ui.com/api/outlined-input/),您会发现它没有 disableUnderline 属性。

我为 disableUnderline 属性赋予了默认值“null”,假设它在未提供时不会呈现。但是当使用 Outlined 变体(没有 disableUnderline 道具)时,我收到以下警告。

React does not recognize the `disableUnderline` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `disableunderline` instead. If you accidentally passed it from a parent component, remove it from the DOM element.

所以我的问题是,有没有办法根本不添加道具。类似于以下伪代码:

return (
  <Select
    {variant !== 'outlined' ? disableUnderline : null} //Pseudo code, just to show what I need
    variant={variant}
    ...
  >
    {children}
  </Select>
);

可能的解决方案

我现在看到的唯一解决方案(我的反应知识有限)是在 CompanySelect 组件中添加一个 if 语句,该语句将检查是否使用了概述的变体。但这意味着我需要在 CompanySelect 代码中有很多重复的代码。

const CompanySelect= (props) => {
  const {
    variant,
    disableUnderline,
    children,
    ...
  } = props;

  if (variant !== 'outlined'){
    return (<Select disableUnderline={disableUnderline} variant={variant} ...> {children} </Select>);
  } else {
    return (<Select variant={variant} ...> {children} </Select>);
  }
};

有没有其他方法可以解决这个问题?

【问题讨论】:

    标签: reactjs material-ui react-props react-component


    【解决方案1】:

    您可以像这样在返回的 JSX 中使用扩展运算符 (...):

    const CompanySelect= (props) => {
      const {
        variant,
        disableUnderline,
        children,
        ...
      } = props;
    
      return (
        <Select
          variant={variant}
          {...(variant !== "outlined" && { disableUnderline: true })}
        >
          {children}
        </Select>
      );
    };
    

    【讨论】:

    • 我将您的代码更改为 {...(variant !== "outlined" &amp;&amp; { disableUnderline: disableUnderline })} 否则当变体 != 'outlined' 时下划线始终禁用。感谢您的单线解决方案
    • @Reggi 你是对的,这是一个错字。不客气。
    【解决方案2】:

    我认为正确的方法是使用React.cloneElement

    类似

    let props = {
        variant: variant,
    };
    
    // Your dynamic props
    if(variant !== 'outlined') {
        props[disableUnderline] = 'your value';
    }
    
    <div>
     {
        React.cloneElement(
         Select,
         props
        )
     }
    </div>
    

    【讨论】:

      猜你喜欢
      • 2019-02-28
      • 1970-01-01
      • 1970-01-01
      • 2021-03-02
      • 2017-09-20
      • 1970-01-01
      • 2020-10-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多