如何解决由后坐力状态触发的 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 的反冲页面并发布你准备好的代码和盒子以获得确认。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。