最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React: Create onClick HOC without using an additional <div > - Stack Overflow

programmeradmin6浏览0评论

I would like to avoid manually adding the onClick property to my custom components.

For that, I thought about a Higher Order Component named WithClick that would wrap my components with the integrated onClick property.

The problem I'm facing is that in order to wrap it, I have to use an additional <div /> tag to access the event property. And this tag is messing up my CSS.

Example :

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

The solution would be a hack, allowing to attach an onClick event to a <React.Fragment /> tag or something similar.

I tried attaching ref to the child, but it doesn't work, I have to treat the ref prop in the child so there's no point doing that.

Do you know a workaround ?

I would like to avoid manually adding the onClick property to my custom components.

For that, I thought about a Higher Order Component named WithClick that would wrap my components with the integrated onClick property.

The problem I'm facing is that in order to wrap it, I have to use an additional <div /> tag to access the event property. And this tag is messing up my CSS.

Example :

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

The solution would be a hack, allowing to attach an onClick event to a <React.Fragment /> tag or something similar.

I tried attaching ref to the child, but it doesn't work, I have to treat the ref prop in the child so there's no point doing that.

Do you know a workaround ?

Share Improve this question asked Feb 4, 2019 at 17:30 B14sB14s 8611 gold badge13 silver badges30 bronze badges 7
  • Can I ask why you want to avoid adding onClick? – georgeperry Commented Feb 4, 2019 at 17:33
  • 1 I am curious what WrappedComponent looks like as I am unsure why you do not want to pass onClick down to it. You still want the user to click a visible object don't you? Whether it's a thumbnail, a button, etc and those things have a layout at the end of the day. – BenHerbert Commented Feb 4, 2019 at 17:35
  • @georgeperry because it generates a lot of redundant code. – B14s Commented Feb 4, 2019 at 17:40
  • I have to agree with @BenHerbert, it doesn't seem sensible. the unnecessary code it generates in the DOM is relatives minute compared to the extra code you would need to write to get around this – georgeperry Commented Feb 4, 2019 at 17:43
  • @georgeperry The question is all about improving the code. Not about "Is it important to lost few seconds ?". – B14s Commented Feb 4, 2019 at 17:47
 |  Show 2 more comments

4 Answers 4

Reset to default 9

While I'm also a little skeptical of the need for this, I could see some specific case where you are adding the same handler to a lot of components and it would be necessary.

ReactDOM.findDOMNode is discouraged by the docs, and deprecated in strict mode. React.cloneElement is a better option.

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

const ComponentWithClick = addClickToComponent(noClickComponent);

I usually make these wrapper components rather than HOC, and if you need to add a property to multiple children, you can do that.

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

 // jsx

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

Wrapper Component

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;

Wrapped component

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

for those who don't want to mess up the CSS, using a span did the work for me.

In some cases it may be handy to use display: contents; on a wrapper element, so additional wrapper with onClick will not break you code.

发布评论

评论列表(0)

  1. 暂无评论