实际重新呈现后,componentDidUpdate()似乎没有被调用

时间:2016-12-15 02:03:25

标签: javascript jquery reactjs

基本代码流是这样的。

item.js

export default class Item extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            modalIsOpen: false,
            logs: []
        };

        this._fetchLogs = this._fetchLogs.bind(this);
        this._fetchAnotherLogs = this._fetchAnotherLogs.bind(this);
    }

    render() {
        let tableBody;

        if (this.state.logs.length > 0) {
            let body = [];
            this.state.logs.forEach((log) => {
                body.push(
                    <tr key={`log${log.id}`}>
                    <td>{log.operator_name} / {log.operator_code}</td>
                    </tr>
                );
            });

            tableBody = (
                <table className="logs">
                <thead>
                <tr>
                <th className="operator">{i18next.t('operator')}</th>
                </tr>
                </thead>

                <tbody>{body}</tbody>
                </table>
            );
        }

        return (
            <div>
            <ul className="tabs">
            <li onClick={this._fetchLogs}>Logs</li>
            <li onClick={this._fetchAnotherLogs}>Another Logs</li>
            </ul>

            <div className="modalContent">
            {tableBody}
            </div>
            </div>
        );
    }

    componentDidUpdate() {
        console.log('didUpdate', $('.ReactModal__Content').height(), $(window).height());
    }

    _fetchLogs() {
        $.ajax({
            context: this,
            url: URL.DEVICE_LOGS(this.props.id),
            success(resp) {
                const logs = resp.data;
                this.setState({logs});
            },
            error(resp) {
                console.log(resp);
            },
        });
    }

    _fetchAnotherLogs() {
        $.ajax({
            context: this,
            url: URL.DEVICE_LOGS_ANOTHER(this.props.id),
            success(resp) {
                const logs = resp.data;
                this.setState({logs});
            },
            error(resp) {
                console.log(resp);
            },
        });
    }
};

因此,当单击<li>元素时,它会调用_fetchLogs(),它将logs状态设置为服务器中的某个数组,而在render()内,它会设置tableBody变量并填充<div className="modalContent">

我想要实现的是通过在状态更改后使用jQuery并且组件重新呈现表,测量表的高度并相应地更改一些样式。

但是componentDidUpdate()注销的是所有孩子(例如,<table>)被重新渲染之前的高度。

例如,如果我说默认高度(没有<table&gt;内容)是170px,则后高(日志的<table>内容)是340px,后高(其他日志的<table>内容为500px,当我第一次点击<li>时,它表示高度为170px,但实际结果高度为340px。如果我点击另一个<li>来获取另一个日志,现在它说高度是340px,这也是错误的,因为它应该是500px。

所以我认为componentDidUpdate()仅在状态发生变化后被调用,而不是实际重新渲染(由于状态变化)完成。是否存在我做错的事情,或者我应该考虑其他选择吗?

编辑1

根据Matthew Herbst的回答,我认为这个回答是合理的,我做了几个改变,但它并没有真正改变。

<div className="modalContent" ref={c => this._modalContent = c}>
    {tableBody}
</div>

componentDidUpdate() {
    console.log('didUpdate', this._modalContent.offsetHeight);
}

(我也尝试用jQuery包装它,但它没有改变......)

我试图通过在componentDidUpdate() console.log()之前添加render()来注销渲染序列和return(尽管无法实现此目的)方式,我知道),它清楚地表明对象数组日志出现在didUpdate日志之前。

1 个答案:

答案 0 :(得分:0)

所以,这里发生的事情是你实际上没有访问componentDidMount中的组件,你正在访问DOM,即使你的组件已经渲染,它可能还没有更新(记住,React有渲染可能已更新的所有组件,然后执行单个DOM差异。

您使用componentDidUpdate是正确的,但您只是访问了错误的内容。你需要的是refs

render中,添加ref

return (
  <div>
    <ul className="tabs">
      <li onClick={this._fetchLogs}>Logs</li>
      <li onClick={this._fetchAnotherLogs}>Another Logs</li>
    </ul>
    <div 
      className="modalContent"
      ref={(myTableRef) => this.myTableRef = myTableRef}
    >
      {tableBody}
    </div>
  </div>
);

然后在componentDidUpdate中,您可以执行以下操作:

componentDidUpdate() {
  console.log('didUpdate', $(this.myTableRef).height(), $(window).height());
}

这应该为您提供表格模型的正确高度。