react ref.current 为空

IT技术 reactjs ref
2021-04-25 05:32:12

我正在开发具有可变时间范围的议程/日历应用程序。要显示当前时间的一行并显示已进行约会的块,我需要计算在给定时间范围内与一分钟对应的像素数。

例如:如果议程从早上 7 点开始,到下午 5 点结束,则总范围为 10 小时。假设日历正文的高度为 1000 像素。这意味着每小时代表 100 个像素,每分钟代表 1.66 个像素。

如果当前时间是下午 3 点。我们距离议程开始还有 480 分钟。这意味着显示当前时间的线应位于距日历主体顶部 796,8 像素 (480 * 1,66) 处。

计算没有问题,但获得议程主体的高度。我想使用 React Ref 来获取高度,但出现错误:ref.current is null

下面是一些代码:

class Calendar extends Component {
    calendarBodyRef = React.createRef();

    displayCurrentTimeLine = () => {
        const bodyHeight = this.calendarBodyRef.current.clientHeight; // current is null
    }

    render() {
        return (
            <table>
                <thead>{this.displayHeader()}</thead>
                <tbody ref={this.calendarBodyRef}>
                    {this.displayBody()}
                    {this.displayCurrentTimeLine()}
                </tbody>
            </table>
        );
    }
}
4个回答

所以关于 refs 的事情是它们不能保证在第一次渲染时设置。您可以确定它们是在期间和之后设置的,componentDidMount因此您有两种前进的方式。

您可以使用回调样式 ref 并基于此设置状态。例如,不是将您的 ref 作为 prop 传递,您可以传递对类似函数的引用this.handleRef,它会在其中执行一些逻辑:

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

或者,您可以保持当前设置,但您必须将您的clientHeight移动到生命周期函数,例如:

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

最终,您不能像那样立即读取 ref 的当前值,您必须在渲染后检查它,然后读取您的bodyHeightfrom 状态。

您可以使用 ref 回调函数。在这种情况下,您不需要使用“React-createRef()”。

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

您将获得 DOM 元素,因此不需要使用“当前”。

如果首选避免在组件状态下存储计算的体高,那么另一种方法是引入第二个ref(即elementDisplayHeightRef),如下所示:

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()
    }
}

这种方法displayCurrentTimeLine()componentDidMount()生命周期钩子(它本身在第一个之后调用)期间调用render()以确保refs在组件逻辑在displayCurrentTimeLine().

希望有帮助!

如果您正在使用react-redux并将您的组件包装在connect函数中,那么您需要像这样传递第四个参数,即 forwardRef。

connect(mapStateToProps, mapDispatchToProps, null, {forwardRef: true})

我希望它会有所帮助。