I'm writing a component that handle some internal state
according to a ref
of it's child (a mouse event related to that child's ref for example).
This component is using a render-prop
to pass on the relevant piece of state
to it's child, and render the child with the ref
attached via React.cloneElement
util.
The problem is that when the child is a class
component, for some reason the ref
is not available, and i can't find a way to render it as it's a react element object with a type of function
(after i clone it of course).
But if the child is just a DOM
node like a div
for example, it is working as expected.
My work-around is to check the type of the child, and if it is a type of function
I'll wrap the cloned element with my own div
, if it's just a dom node then render as is.
However, i would like to not wrap the child with an extra div
as i don't want to add unnecessary DOM
nodes.
Here is a basic code example, most code removed for brevity:
The Parent component:
class Parent extends Component {
attachRef = node => {
this.ref = node;
}
render() {
const { render } = this.props;
const { someValue } = this.state;
const Child = render(someValue);
const WithRef = React.cloneElement(Child, {
ref: this.attachRef
});
if (typeof WithRef.type === 'string') { // node element
return WithRef;
}
else if (typeof WithRef.type === 'function') {
// this is a react element object.. not sure how to render it
// return ?
} else {
// need to find a way to render without a wrapping div
return (
<div ref={this.attachRef}>{Child}</div>
);
}
}
}
The usage:
class App extends Component {
render() {
return (
<div>
<Parent render={someValue => <div> {someValue}</div>} />
<Parent render={someValue => <Menu someValue={someValue} />} />
</div>
);
}
}
When i render regular DOM nodes like the first example it works fine, when i try to render the Menu
(which is a class
component) it doesn't work as mentioned above.