2

I'm trying to use React.createRef() to access the dimensions of a DOM element in React.

I create in in the constructor like

constructor(props) {
super(props);
this.container = React.createRef()
}

And assigning it like

  <div id="container"
  ref={this.container}
  >...children</div>

However when I log this out from within componentDidMount()

componentDidMount(){
console.log(this.container);
}

I see {current: null} in the console. But if I expand this object I can see everything I want access to like clientHeight which has a value.

enter image description here

How do I access these attributes? At the moment this.container.current.clientHeight returns null.

Thanks

L-R
  • 418
  • 1
  • 7
  • 23
  • 1
    Are you trying to log `client` or `clientHeight`? – Chris Feb 05 '19 at 14:19
  • clientHeight - typo in original question – L-R Feb 05 '19 at 14:25
  • Check out this link https://stackoverflow.com/questions/44074747/componentdidmount-called-before-ref-callback – Harvey Feb 05 '19 at 14:31
  • Thanks but that doesn't really resolve my issue as this doesn't appear to be true `React guarantees that refs are set before componentDidMount or componentDidUpdate hooks. But only for children that actually got rendered.` As the child has been rendered. – L-R Feb 05 '19 at 14:42
  • Did you ever figure this out? I'm having the same issue... – the-nick-wilson May 31 '19 at 16:09
  • Check if you have any asynchronous code that can prevent referenced element from rendering. If so make sure that you use your ref AFTER the element has been rendered. – Adrian Solarczyk May 31 '20 at 12:42

1 Answers1

0

here is my sample code:

class Badge extends React.Component {
constructor(props) {
super(props);

this.textWidth = React.createRef();
this.state = {
  width: ""
};
}

 componentDidMount() {
this.textWidth.current.addEventListener("load", this.getWidth());
}

 getWidth = () => {
this.setState({
  width: this.textWidth.current.clientWidth + 30
 });
};

render() {
  return (
  <div
    style={{
      width: this.state.width
     }}
     className="badge"
   >
     <p ref={this.textWidth}>{this.props.children}</p>
   </div>
  );
  }
 }
  • Why are you adding a load event listener? Is this not what componentDidMount should be doing? – L-R Feb 05 '19 at 14:24
  • because if you don't use this you won't get client attr. Content in ref element takes time to load. –  Feb 05 '19 at 14:26
  • Where have you got this info from? I can't see anywhere in the react docs which suggest you should do this. It doesn't seem very reacty to call addEventListener. It's also still null if I try this `Cannot read property 'addEventListener' of null` – L-R Feb 05 '19 at 14:28
  • componentDidMount(){ this.container.current.addEventListener('load', () => { console.log(this.container.current.clientWidth); }) } – L-R Feb 05 '19 at 14:33
  • 1
    Hi raju, and welcome to stackoverflow. Rather than pasting code and 'try this' answers, some explaination providing the answer could be better. – Harvey Feb 05 '19 at 14:40
  • I think you are doing something wrong. check my sandbox code and open console. https://codesandbox.io/s/145wq8w1m3 –  Feb 05 '19 at 14:41
  • @Harvey I just gave him a live example code so he can understand clearly. –  Feb 05 '19 at 14:42
  • Thanks for the help. I know have it working, wrapping the component being rendered in `App` in the div rather than rendering the div within the child component – L-R Feb 05 '19 at 15:01
  • Great! mark it as answered it will motivate me and other people know that this is a correct answer. –  Feb 05 '19 at 15:02
  • @RajuChoudhary how could I make this example using React hooks? – Francis Rodrigues Apr 22 '19 at 03:31