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 | Show 2 more comments4 Answers
Reset to default 9While 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.
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