We're using a higher-order component to provide validation in our forms and it is responsible for acting on all change events. The problem I'm having stems from not being able to add a onChange
handler to the wrapped component itself so the HoC wraps it in a div. We have a flex-based grid-system that really does not appreciate that extra div.
The HoC basically looks like this:
function withValidation(TargetComponent, options = {}) {
class ValidatingComponent extends Component {
...
render() {
return (
<div
ref={(_target) => { this._target = _target; }}
onChange={this.onChange}
>
<TargetComponent
{...this.props}
{...this.state}
onSubmit={this.onSubmit}
/>
</div>
);
}
}
return ValidatingComponent;
}
The first thing I tried was to simply remove the wrapper
render() {
return (
<TargetComponent
{...this.props}
{...this.state}
ref={(_target) => { this._target = _target; }}
onChange={this.onChange}
onSubmit={this.onSubmit}
/>
)
}
But that just passes the onChange
as a prop to the wrapped component and I kind of don't want to have to call it manually. I tried to attach a regular vanilla event-listener by doing
componentDidMount() {
findDOMNode(this._target).addEventListener('change', this.onChange);
}
But that didn't work. The onChange
was never triggered, I'm guessing it's not catching whatever synthetic event it is that React dispatches.
Is there any way I can convince a React component to listen for change events on itself? I really don't want to have to pass that callback all the way down the component tree untill I reach the relevant <input>
and call it from there.
I realize this question seems similar to this one but they're dealing with custom DOM events. I'm not.
EDIT
In case I wasn't being clear about what I'm trying to do I made a fiddle as well, it's here.
When <TargetComponent />
is wrapped by a div
and the onChange handler is attached to that div the form works but when onChange
is just passed as a prop to the TargetComponent itself it doesn't. I need some way to tell my HoC to actually listen to events and not just pass a function. I'm not wrapping input's here, I'm wrapping entire forms.