如何将现有InputProps与子组件中的其他InputProps结合

时间:2019-10-31 13:54:13

标签: reactjs material-ui

我已经编写了具有自定义样式的material-ui TextField(称为CustTextField1)的自定义版本。我希望基于CustTextField1的样式开发另一种自定义名为CustTextField2的自定义。我已经将InputProps应用于CustTextField1,并且希望它们与我在此处应用的一些其他InputProps一起在CustTextField2中使用。这是代码的相关部分。出现在应用于CustTextField2的InputProps(即,密码眼睛图标),但似乎覆盖了已在CustTextField1中设置的InputProps。对于如何将两者结合在一起的任何帮助将不胜感激。

function CustTextField1(props) {
  return (
    <TextField
      InputProps={{     
        disableUnderline: true,
        classes: {
          root: textFieldStyle.rootInputStyle,
          focused: textFieldStyle.focused,
          disabled: textFieldStyle.disabled,
          error: textFieldStyle.error
        }
      }}

      {...props}
    />
)
}
function CustTextField2(props) {
  return (
    <CustTextField1
    InputProps={{    
        endAdornment: (
                    <InputAdornment position="end">
                        <IconButton>
                            {showPassword ? <Visibility/> : <VisibilityOff/>}
                        </IconButton>
                    </InputAdornment>
                ),
          ...props.InputProps
        }
      }}

      {...props}
    />
)
}

我希望CustTextField1中的InputProps样式与CustTextField2中的其他InputProps样式相结合。

!!更新!!

代码沙箱(原始问题)-https://codesandbox.io/s/fervent-smoke-g8nsb

代码沙箱(解决方案),衷心感谢以下 toutpt 中的帖子-https://codesandbox.io/s/stoic-mclean-9kh1r

3 个答案:

答案 0 :(得分:1)

要继承时,应始终注意合成。 因此,首先您应该照顾要覆盖的道具。

在下面的示例中,CustTextField1将负责InputProps来添加基础,并让用户覆盖它们。 但是因为有classes也是一个对象,所以我需要照顾它。

function CustTextField1({ InputProps, ...props }) {
    const iprops = Object.assign({
        disableUnderline: true,
    }, InputProps, {
        classes: Object.assign({
            root: textFieldStyle.rootInputStyle,
            focused: textFieldStyle.focused,
            disabled: textFieldStyle.disabled,
            error: textFieldStyle.error,
        }, InputProps.classes || {})
    });
    return <TextField InputProps={iprops} {...props} />;
}

在您的示例中,您不会破坏道具,因此,在传播道具时,您会完全覆盖InputProps

 InputProps={}
 {...props}

因此,如果props包含InputProps,则需要两次:

InputProps={} // the one define by CustTextField1
... 
InputProps={} // the one define by CustTextField2

答案 1 :(得分:1)

React中的Prop注入与Javascript对象的处理方式相似,即下一个匹配的键将覆盖前一个键。在对象的上下文中,您正在执行的操作是将InputProps替换为InputProps的{​​{1}}。对于您的特定用例,您要通过在将this.props{...this.props}合并之前放置InputProps来覆盖每个道具。

CustTextField2

通过这种方式,您将根据自己的喜好传递所有带有道具function CustTextField2(props) { return ( <CustTextField1 {...props} InputProps={{ endAdornment: ( <InputAdornment position="end"> <IconButton> {showPassword ? <Visibility/> : <VisibilityOff/>} </IconButton> </InputAdornment> ), ...props.InputProps } }} /> ) } 的道具。

答案 2 :(得分:0)

您要声明两次相同的道具,因此最后应用的道具将覆盖之前的道具。如果您已经麻烦创建两个单独的组件,那么从头开始第二个组件而不使用第一个组件会更有意义。

但是,我认为更好的解决方案是使用单个组件并添加道具以切换所需的其他配置:

function CustTextField(props) {
  let inputProps = {
    disableUnderline: true,
    classes: {
      root: textFieldStyle.rootInputStyle,
      focused: textFieldStyle.focused,
      disabled: textFieldStyle.disabled,
      error: textFieldStyle.error
    },
    endAdornment: props.adornment ? (
      <InputAdornment position="end">
        <IconButton> {true ? <Visibility /> : <VisibilityOff />}</IconButton>
      </InputAdornment>
    ) : null
  };

  return <TextField InputProps={inputProps} {...props} />;
}

....

<CustTextField adorned={true}/>