React:在不使用额外的 <div /> 的情况下创建 onClick HOC

IT技术 javascript reactjs
2021-05-27 10:51:15

我想避免手动将onClick属性添加到我的自定义组件中。

为此,我想到了一个名为的高阶组件WithClick,它将用集成onClick属性包装我的组件

我面临的问题是,为了包装它,我必须使用额外的<div />标签来访问事件属性。这个标签搞乱了我的 CSS。

例子 :

import React, { Component } from 'react'

const WithClick = (WrappedComponent) => {
  class BaseComponent extends Component {
    render () {
      return (
        <div onClick={this.props.onClick}>
          <WrappedComponent {...this.props} />
        </div>
      )
    }
  }

  return BaseComponent
}

export default WithClick

解决方案是 hack,允许将 onClick 事件附加到<React.Fragment />标签或类似的东西。

我尝试将 ref 附加到孩子身上,但它不起作用,我必须对待孩子中的 ref props,所以这样做没有意义。

你知道解决方法吗?

4个回答

虽然我也有点怀疑这样做的必要性,但我可以看到一些特定的情况,您将相同的处理程序添加到许多组件中,这将是必要的。

ReactDOM.findDOMNode文档不鼓励使用,并在严格模式下弃用。React.cloneElement 是更好的选择。

const addClickToComponent = ({component}) => (
  React.cloneElement(component, {
    onClick: someComplicatedClickFunction,
  }
);

const ComponentWithClick = addClickToComponent(noClickComponent);

我通常制作这些包装器组件而不是 HOC,如果您需要向多个子项添加属性,您可以这样做。

const ClickWrapper = ({children}) => (
  <React.Fragment>
    {React.Children.map(children, child => (
      React.cloneElement(child, {
       onClick: someComplicatedClickFunction,
      )
     )
    }
  </React.Fragment>
 );

 // jsx

 <ClickWrapper>
   <ChildComponent />
   <ChildComponent />
   <ChildComponent />
 </ClickWrapper>

包装组件

class Wrapper extends Component {
    render() { 
        return ( 
        <React.Fragment>
            <WrappedComponent />
        </React.Fragment>);
    }
    componentDidMount(){
        //This will return the container of WrappedComponent
        ReactDOM.findDOMNode(this).onclick = this.props.onClick
    }
}
export default Wrapper;

包裹组件

class WrappedComponent extends Component {
  render(){
    return(
      <div className="wrappedComp"><span>I am wrapepd component</span></div>
    )
  }
}

对于那些不想弄乱 CSS 的人来说,使用 span 对我有用。

在某些情况下,display: contents;在包装器元素上使用可能很方便,因此额外的包装器onClick不会破坏您的代码。