React ref.current is null React ref.current is null reactjs reactjs

React ref.current is null


So the thing about refs is that they aren't guaranteed to be set on first render. You can be sure they are set during and after componentDidMount so you have two ways going forward.

You could use the callback style ref and set state based on that. E.g. instead of passing your ref as the prop, you can pass in a reference to a function like this.handleRef and it would do some logic in there:

  handleRef = r => {    this.setState({ bodyHeight: r.clientHeight})    this.calendarBodyRef.current = r;  };

Or, you could keep your current set up but you would have to move your clientHeight bit to a lifecycle function like:

  componentDidMount() {    this.setState({ bodyHeight: this.calendarBodyRef.current.clientHeight });  }

Ultimately, you can't immediately read the current value of a ref like that, you would have to check it after the render and then read your bodyHeight from state.


You could use a ref callback function. In this case, you wouldn't need to use "React-createRef()".

<tbody ref={this.calendarBodyRef}>...calendarBodyRef = (e) => {console.log(e)}

You will get the DOM Element back and therefore don't need to use "current".


If avoiding storage of the calculated body height in component state is preferred, then another approach would be to introduce an second ref (ie elementDisplayHeightRef) like so:

class Calendar extends React.Component {    /* Create a ref for the body */    calendarBodyRef = React.createRef();    /* Create a ref for element where height will be displayed */    elementDisplayHeightRef = React.createRef();    displayCurrentTimeLine = () => {        /* Calculate body height from ref */        const bodyHeight = this.calendarBodyRef.current.clientHeight;            /* Update display */        this.elementDisplayHeightRef.current.innerText = `bodyHeight:${bodyHeight}`    }    render() {        return (            <table>                <thead></thead>                <tbody ref={this.calendarBodyRef}>                    <td><td>Some row</td></td>                    {/* Bind display ref */ }                    <tr><td ref={this.elementDisplayHeightRef}></td></tr>                </tbody>            </table>        );    }    /* Add did mount life cycle hook, and trigger display of body height */    componentDidMount() {      this.displayCurrentTimeLine()    }}

This approach calls displayCurrentTimeLine() during the componentDidMount() life cycle hook (which itself is called after the first render()) to ensure that both refs are fully initialised, before the component logic interacts with them in displayCurrentTimeLine().

Hope that helps!