Reputation: 2565
I've got a component and want to use the Office-UI-Fabric-react component "Callout" when the mouse is hovering over a "Persona"-element.
The "Callout" works if I reference the 'div' enclosing the "Persona"-element
(using ref={this.setPersonaRef}
),
but componentRef={this.setPersonaRef}
in the "Persona"-element leads to
Exception in CalloutContent.componentDidMount(): TypeError: element.getBoundingClientRect is not a function
Here is the component:
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Persona,PersonaSize } from 'office-ui-fabric-react/lib/Persona';
import { Callout } from 'office-ui-fabric-react/lib/Callout';
import {IHoverPersonaProps} from './IHoverPersonaProps';
import {IHoverPersonaState} from './IHoverPersonaState';
export default class HoverPersona extends React.Component < IHoverPersonaProps,IHoverPersonaState > {
private personaRef: any;
constructor(props) {
super(props);
this.state = {
hover: false
};
this.setPersonaRef = this.setPersonaRef.bind(this);
}
setPersonaRef(element) {
this.personaRef = element;
}
MouseEnter() {
this.setState({hover:true})
}
MouseLeave() {
this.setState({hover:false})
}
public render() : React.ReactElement < IHoverPersonaProps > {
return <div onMouseEnter={this.MouseEnter.bind(this)} onMouseLeave={this.MouseLeave.bind(this)} >
<Persona {...this.props} size={PersonaSize.extraSmall} primaryText={this.props.value} componentRef={this.setPersonaRef} />
{ this.state.hover &&
<Callout
className="ms-CalloutExample-callout"
ariaLabelledBy={'callout-label-1'}
ariaDescribedBy={'callout-description-1'}
coverTarget={false}
gapSpace={0}
target={this.personaRef}
setInitialFocus={true}
>
<div className="ms-CalloutExample-header">
<p className="ms-CalloutExample-title" id={'callout-label-1'}>
Test
</p>
</div>
<div className="ms-CalloutExample-inner">
<Persona {...this.props} size={PersonaSize.large} primaryText={this.props.value} />
</div>
</Callout>
}
</div>;
}
}
How can I resolve the exception?
Upvotes: 13
Views: 57523
Reputation: 2858
Because to use getBoundingClientRect
or other similar methods you need to point current
property of ref
.
From documentation:
useRef (or simple class ref) returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component.
Example:
function App() {
const inputRef = useRef();
const scrollHandler = _ => {
console.log(inputRef.current.getBoundingClientRect());
};
useEffect(() => {
window.addEventListener("scroll", scrollHandler, true);
return () => {
window.removeEventListener("scroll", scrollHandler, true);
};
}, []);
return (
<div ref={inputRef} className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
Codesandbox (to see result scroll and instead of codesandbox console use browser console)
Upvotes: 28
Reputation: 61
If you're defining the ref
on the component level
like this:
<SomeComponent ref={yourRef} />
you'll get getBoundingClientRect()
from the node
property that comes from the first element rendered on the component
yourRef.current.node.getBoundingClientRect()
Upvotes: 1