由后坐力状态触发的 useEffect 在 safari 中无法按预期工作

问题描述

我想在组件外的状态改变时触发 { "compilerOptions": { "target": "ES2020","lib": [ "dom","dom.iterable","esnext" ],"allowJs": true,"skipLibCheck": true,"strict": false,"forceConsistentCasingInFileNames": true,"noEmit": true,"esModuleInterop": true,"module": "esnext","moduleResolution": "node","resolveJsonModule": true,"isolatedModules": true,"jsx": "preserve","baseUrl": ".","downlevelIteration": true,"paths": { "~components/*":["src/components/*"],"~styles/*":["src/styles/*"],"~store/*":["src/store/*"],"~snippets/*":["src/snippets/*"],"~utils/*":["src/utils/*"],"~interfaces/*":["src/interfaces/*"],"~services/*":["src/services/*"],"~transformer/*":["src/transformer/*"],} },"include": [ "next-env.d.ts","**/*.ts","**/*.tsx" ],"exclude": [ "node_modules" ] } 点击。

当更新状态作为 prop 传递并且 useEffect 函数被执行时,一切都按预期工作。

当更新状态作为 input type="file" 传递时,它似乎不起作用(但仅在 safari 中) - 它按预期触发 useEffect 但 useRecoilState 不起作用。

这是出现问题的工作代码https://codesandbox.io/s/useeffect-recoil-trigger-vs-prop-w7lwq?file=/src/index.js:315-329

这是代码

inputRef.current.click()

解决方法

这是最好奇的。如果您使用 useEffect 而不是 useLayoutEffect(但也仅在 Safari 中,FF 和 Chromium 的行为符合预期),两者都将不起作用。因为在 Safari 中,如果您使用 useLayoutEffect 它可以工作,我怀疑 Safari 和 Reacts 异步性质不太好。

我的猜测是 Safari 对以编程方式打开对话框的限制非常严格。 所以我认为 Safari 在某处丢失了用户引发的点击是 React 的整个异步过程。

它只使用与 prop/useState 相关的 useLayoutEffect 的原因是这种效果将在与操作本身相同的渲染周期中触发(与称为 async 的 useEffect 相反) .所以 Safari 仍然知道用户触发了一个结果是打开对话框的操作,Safari 很乐意允许。

但是将其与反冲一起使用(就此而言,可能与任何其他支持并发模式的外部状态管理一起使用),情况会有所不同。

因为您正在设置外部状态,所以 React 不会立即触发提交阶段。特别是反冲在短时间内收集状态更新,然后在 React 中触发新的提交和渲染周期。所以用户动作、状态更新和渲染阶段是三个不同的时间片。由于反冲支持并发模式,这甚至可能意味着提交的多个阶段,因此渲染可能会被搁置更长时间。 这一切都是异步发生的,因此监听反冲触发器的 useLayoutEffect 在不同的渲染周期中执行,然后用户点击按钮。

而且我认为这就是它在 Safari 中不起作用的原因。 Safari 不会将这两者连接在一起,或者说已经“忘记”了用户单击了一个按钮。在设置后坐力状态后的渲染周期中,Safari 只看到点击文件输入的命令式调用,但不记得用户点击触发了此周期中的任何操作。

如果我所描述的确实是这里发生的事情,我会做的是去 Github 的反冲页面并发布你准备好的代码和盒子以获得确认。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...