无法在初始渲染中找到 ref

IT技术 reactjs redux react-redux
2021-05-07 07:53:40

我刚刚在官方文档中读到 componentDidUpdate 在第一次渲染时没有被调用,我想这可能就是为什么我的这个组件在第一次渲染时没有定义 dom 的原因。

这是一个弹出模式,当页面需要编辑时弹出。

我还有其他方法可以解决这个问题吗?

componentDidUpdate() {
    this.renderSingularForm();
}

renderSingularForm() {
    let dom = ReactDOM.findDOMNode( this.refs.singularForm );
    if ( this.props.pageObjToEdit && dom ) {
        // DOESN'T GO HERE ON FIRST RENDER BECAUSE DOM IS NULL

        createForm( window, dom, this.props.pageObjToEdit );
    }
}

render() {
    if ( this.props.pageObjToEdit ) {
        return (
            <div>
                <div ref="singularForm" />
            </div>
        );
    }
    else {
        return null;
    }
}
2个回答

这是您如何使用 refs 的问题。你不应该再使用字符串引用,因为它们很快就会被弃用大多数人现在都在使用内联 ref ( ref={ref => this.input = ref}),但是当您这样做时,组件在第一次呈现时会收到一个null值。然后在第二次渲染时,refs 将正确分配给 DOM 元素。

为了解决这个问题,你应该为refprop提供一个类方法而不是一个内联函数。

例子:

这:

render() {
    return (
        ...
        <div ref="singularForm" />
        ...
    )
}

应该:

applyRef = ref => {
    this.singularForm = ref;
}
render() {
    return (
        ...
        <div ref={this.applyRef} />
        ...
    )
}

当您使用类方法应用 ref 时,它只会在实际元素添加到 dom 时调用一次,因此您不应再获取初始null值。

10/18 更新:

您现在可以使用 newReact.createRef创建您的 refs 来完全避免这个问题

您可以并且应该使用componentDidMount来安全地获取 DOM 元素或引用

来自 DOCS:

componentDidMount() 在组件安装后立即调用。需要 DOM 节点的初始化应该在这里进行。
...

但是,当您需要在渲染取决于其大小或位置的内容之前测量 DOM 节点时,对于模态和工具提示等情况,它可能是必要的。

另请注意,您使用的是旧的 ref API
您应该使用新的ref API

运行示例:

class App extends React.Component {
  componentDidMount() {
    console.log(this.myDiv.id);
  }

  render() {
    return (
      <div>
        <div id="some-id" ref={ref => (this.myDiv = ref)}>some div</div>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>