草庐IT

javascript - componentDidMount 在 ref 回调之前被调用

coder 2023-07-03 原文

问题

我正在使用内联函数定义设置一个 react ref

render = () => {
    return (
        <div className="drawer" ref={drawer => this.drawerRef = drawer}>

然后在 componentDidMount 中未设置 DOM 引用

componentDidMount = () => {
    // this.drawerRef is not defined

我的理解是 ref 回调应该在挂载期间运行,但是添加 console.log 语句显示 componentDidMount之前被调用 ref 回调函数。

我看过的其他代码示例(例如 github 上的 this discussion)表明了相同的假设,componentDidMount 应该在任何 ref 回调之后 被调用在render中定义,甚至是stated in the conversation

So componentDidMount is fired off after all the ref callbacks have been executed?

是的。

我正在使用 React 15.4.1

我尝试过的其他方法

为了验证 ref 函数是否被调用,我尝试在类上定义它

setDrawerRef = (drawer) => {
  this.drawerRef = drawer;
}

然后在render

<div className="drawer" ref={this.setDrawerRef}>

在这种情况下,控制台日志显示回调确实在 之后 componentDidMount

被调用

最佳答案

简答:

React 保证 refs 设置在 componentDidMount 之前或 componentDidUpdate钩子(Hook)。但仅限于实际渲染的 child 。

componentDidMount() {
  // can use any refs here
}

componentDidUpdate() {
  // can use any refs here
}

render() {
  // as long as those refs were rendered!
  return <div ref={/* ... */} />;
}

请注意,这并不意味着“React 总是在这些钩子(Hook)运行之前设置所有 refs”。
让我们看一些没有设置 refs 的例子。


不会为未呈现的元素设置 Refs

React 只会为您实际<​​strong>从渲染返回的元素调用 ref 回调。

这意味着如果你的代码看起来像

render() {
  if (this.state.isLoading) {
    return <h1>Loading</h1>;
  }

  return <div ref={this._setRef} />;
}

最初是this.state.isLoadingtrue ,你应该期待this._setRefcomponentDidMount之前被调用.

这应该是有道理的:如果您的第一个渲染返回 <h1>Loading</h1> ,React 不可能知道在某些其他条件下它会返回其他需要附加 ref 的东西。也没有任何东西可以将 ref 设置为: <div>未创建元素,因为 render()方法说它不应该被渲染。

所以对于这个例子,只有componentDidMount会开火。但是,this.state.loading更改为 false ,你会看到this._setRef先附上,然后是componentDidUpdate会开火。


注意其他组件

请注意,如果您将带有 refs 的子组件传递给其他组件,它们有可能正在做一些阻止渲染的事情(并导致问题)。

例如,这个:

<MyPanel>
  <div ref={this.setRef} />
</MyPanel>

如果 MyPanel 将不起作用不包括 props.children在其输出中:

function MyPanel(props) {
  // ignore props.children
  return <h1>Oops, no refs for you today!</h1>;
}

同样,这不是错误:React 不会设置 ref,因为 DOM 元素未创建


如果 Refs 被传递给嵌套的 ReactDOM.render(),则不会在生命周期之前设置它们

与上一节类似,如果您将带有 ref 的子项传递给另一个组件,则该组件可能会做一些阻止及时附加 ref 的事情。

例如,它可能不会从 render() 返回 child , 而不是调用 ReactDOM.render()在生命周期钩子(Hook)中。您可以找到此 here 的示例.在那个例子中,我们呈现:

<MyModal>
  <div ref={this.setRef} />
</MyModal>

但是MyModal执行 ReactDOM.render()调用它的 componentDidUpdate生命周期方法:

componentDidUpdate() {
  ReactDOM.render(this.props.children, this.targetEl);
}

render() {
  return null;
}

自 React 16 以来,此类生命周期中的顶级渲染调用将被延迟,直到整个树的生命周期运行完毕。这可以解释为什么您没有及时看到附加的引用。

这个问题的解决方案是使用 portals而不是嵌套 ReactDOM.render调用:

render() {
  return ReactDOM.createPortal(this.props.children, this.targetEl);
}

这边我们的<div>具有 ref 实际上包含在渲染输出中。

因此,如果您遇到此问题,您需要确认您的组件和 ref 之间没有任何可能延迟渲染子项的内容。

不要使用setState存储引用

确保你没有使用 setState将 ref 存储在 ref 回调中,因为它是异步的并且在它“完成”之前,componentDidMount将首先执行。


还是个问题?

如果以上提示均无帮助,请在 React 中提交问题,我们将进行查看。

关于javascript - componentDidMount 在 ref 回调之前被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44074747/

有关javascript - componentDidMount 在 ref 回调之前被调用的更多相关文章

  1. ruby - 如何在 Rails 4 中使用表单对象之前的验证回调? - 2

    我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser

  2. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  3. ruby - 有人可以帮助解释类创建的 post_initialize 回调吗 (Sandi Metz) - 2

    我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法

  4. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  5. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  6. ruby - 调用其他方法的 TDD 方法的正确方法 - 2

    我需要一些关于TDD概念的帮助。假设我有以下代码defexecute(command)casecommandwhen"c"create_new_characterwhen"i"display_inventoryendenddefcreate_new_character#dostufftocreatenewcharacterenddefdisplay_inventory#dostufftodisplayinventoryend现在我不确定要为什么编写单元测试。如果我为execute方法编写单元测试,那不是几乎涵盖了我对create_new_character和display_invent

  7. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  8. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

  9. ruby - 如何找到调用当前方法的方法 - 2

    如何找到调用此方法的位置?defto_xml(options={})binding.pryoptions=options.to_hifoptions&&options.respond_to?(:to_h)serializable_hash(options).to_xml(options)end 最佳答案 键入caller。这将返回当前调用堆栈。文档:Kernel#caller.例子[0]%rspecspec10/16|===================================================62=====

  10. ruby-on-rails - 使用 HTTParty 的非常基本的 Rails 4.1 API 调用 - 2

    Rails相对较新。我正在尝试调用一个API,它应该向我返回一个唯一的URL。我的应用程序中捆绑了HTTParty。我已经创建了一个UniqueNumberController,并且我已经阅读了几个HTTParty指南,直到我想要什么,但也许我只是有点迷路,真的不知道该怎么做。基本上,我需要做的就是调用API,获取它返回的URL,然后将该URL插入到用户的数据库中。谁能给我指出正确的方向或与我分享一些代码? 最佳答案 假设API为JSON格式并返回如下数据:{"url":"http://example.com/unique-url"

随机推荐