react Bug: < iframe /> onLoad 在通过移动 DOM 节点触发的重新加载后未被触发,

q0qdq0h2  于 5个月前  发布在  React
关注(0)|答案(8)|浏览(65)

当一个 <iframe /> DOM 节点被移动到树中的不同位置时,Chrome 会触发重新加载。然而,这个重新加载并不通知通过 onLoad= 注册的事件处理程序。换句话说:

  • 如果通过 onLoad={myCallback} 注册了事件处理程序,它将不会被触发。
  • 如果通过 iframe.addEventListener("load", myCallback, false) 注册了事件处理程序,它将会被触发。

React 版本:16.13.1

重现步骤

打开下面的代码示例,并使用旁边的箭头按钮将 iframe 向下移动。
https://codesandbox.io/s/serverless-surf-k1ypg?file=/src/App.js

当前行为

iframe 不再显示 "Initialized"。

预期行为

iframe 应该显示 "Initialized"。

其他注意事项

如果你将 setIframeContent(e.currentTarget); 移动到 nativeLoad 并重复上述步骤,它将按预期工作。这个 bug 在 Firefox 中不会出现。

gpfsuwkq

gpfsuwkq1#

潜在相关?
react/packages/react-dom/src/events/ReactDOMEventListener.js
第318行到第324行
| | }elseif(nearestMounted!==targetInst){ |
| | // 如果在提交该组件的挂载之前收到事件(例如:img onload),暂时忽略它(即,将其视为非React树上的事件)。我们还可以考虑将事件排队并在挂载后分发。 |
| | targetInst=null; |
| | } |

puruo6ea

puruo6ea2#

iframe应该显示"Initialized"。
只有在实际的代码沙箱浏览器预览中才能在火狐75中复现这个问题。它在独立页面(https://k1ypg.csb.app/)或Chrome 81中无论视图如何都能正常工作。

ne5o7dgx

ne5o7dgx3#

火狐浏览器部分很有趣——我在那里无法复现。我只在独立的页面上尝试过,并设法用Chrome复现了它:

$x_{1c0d}^{1}_{x}$

这只发生在向下箭头的情况下,因为它会使React移动实际的DOM节点。向上箭头将移动前一个节点。

还请参见以下古腾堡问题,许多人都能复现,以及底层修复:

  • $x_{1e0f}^{1}_{x}$

  • $x_{1e1f}^{1}_{x}$

bttbmeg0

bttbmeg04#

看起来像macOS?
以下是我在Ubuntu 18.04上的测试结果:
Chrome版本81.0.4044.122(官方构建)(64位):

Firefox 75.0(64位):

我最近自己遇到了一些关于iframe的问题,但这些问题都与嵌套的iframe无关(这适用于codesandbox的预览窗口)。通常情况下,我会:

  • 不使用document.write,而是使用ReactDOM.createPortal
  • load事件之前或之后不进行portal(如果你需要进行hydrating操作,你需要以被动效果处理)

我发现在firefox中,在load事件之前调用document.write会被丢弃。

hvvq6cgz

hvvq6cgz5#

看起来像macOS?
是的!
这是我在Ubuntu 18.04上的结果:
不错!我们在这里看到这么多操作系统/浏览器不一致,真是有趣——我没想到会这样。我想知道这些iframe是否在不同的操作系统上有不同的方式/顺序重新加载?此外,让我只是链接到iframe重新加载问题,以防评论中有相关的内容:

不要使用document.write,而是使用ReactDOM.createPortal
不要在load事件之前或document.readyState === "complete"(如果你正在进行内容更新,你需要在被动效果中处理它)
Portals听起来是一个更好的Gutenberg修复的好主意。我只是玩了一下,我有一些额外的发现:

设置<iframe srcDoc="<!DOCTYPE html>"可以解决我的问题:

https://codesandbox.io/s/dazzling-tdd-50r9o?file=/src/App.js

useRef只有在设置了srcDoc时才始终有效

否则,ref.current保持为null。如果你将ref设置为自定义回调,它将使用正确的DOM节点被调用:https://codesandbox.io/s/young-water-km9v5?file=/src/App.js
这似乎是一种竞争条件,因为我得到了不一致的结果:

我发现在加载事件之前调用document.write会被Firefox丢弃。
学到新知识了,谢谢!

ev7lccsx

ev7lccsx6#

MacOS无法在Chrome或Firefox上使用最新版本的React进行复现,也无法在16.12版本上进行复现。

u3r8eeie

u3r8eeie7#

找到如何轻松且一致地重现这个bug:
MacOs 11.6 20G165
Chrome Version 101.0.4951.64 (Official Build) (x86_64)
react, react-dom 17.0.2
要重现,请关闭所有浏览器扩展,并在示例中使用代码沙箱-它开始一致地重现。

yjghlzjz

yjghlzjz8#

这也发生在我身上:
[版本1.45.131 Chromium: 107.0.5304.110(官方构建)(64位)]

相关问题