react SuspenseList尾部属性在重新渲染时不起作用,

hfsqlsce  于 5个月前  发布在  React
关注(0)|答案(5)|浏览(77)

你想要请求一个功能还是报告一个bug?

我正在报告一个可能的bug或者请求澄清。

当前的行为是什么?

当一个带有SuspenseList重新渲染的组件(例如,当它被传递一个新的资源时),SuspenseList组件仍然尊重revealOrder="forwards"或revealOrder="backwards"属性,但不尊重tail="collapsed"或tail="hidden"属性。

如果当前行为是一个bug,请提供重现步骤,如果可能的话,提供一个最小化的演示问题。如果你能运行你的代码并且它除了React之外没有其他依赖项,那么你的bug会得到更快的修复。请将链接粘贴到下面的JSFiddle( https://jsfiddle.net/Luktwrdm/ )或CodeSandbox( https://codesandbox.io/s/new )示例中:

https://codesandbox.io/s/exciting-cherry-g9uc9
为了查看bug:

  1. 刷新Code Sandbox浏览器,看到"Loading profile..."显示,而"Loading posts..."没有显示,这是因为尾部被折叠了。这是预期的行为。
  2. 按“下一步”按钮。两个"Loading Profile..."和"Loading posts..."都显示出来。尾部不再折叠。

预期的行为是什么?

预期的行为是在按下“下一步”按钮时,尾部应该被折叠。"Loading profile..."应该显示,但不应该显示"Loading posts..."

这个问题影响了哪些版本的React,以及哪个浏览器/操作系统?在之前的React版本中是否有效?

这个问题只影响React的实验性并发模式构建。

ghhkc1vu

ghhkc1vu1#

这是预期的行为 - 尽管令人困惑。这是因为在您的示例中,这些不是“新”的行。它们是对现有行的更新。如果您改为提供一个“键”,该键是页面上的唯一键,无论是在父级还是在行上,以使它们成为新行,那么它将按预期工作。
这是因为我们不想“删除”已经存在的项目。当所有行都处于挂起状态时,这一点并不明显,但当只有部分行重新挂起时,情况就开始变得奇怪了。
实际上,如果您在底部添加一个不挂起的额外行,那么 revealOrder="forwards" 行为也不会被保留,因为它们都被认为是更新后的“头”的一部分。
总的来说,我认为正确的解决方案就是避免这种情况,并使用一个键来代替。

31moq8wy

31moq8wy2#

谢谢!这让我稍微明白了一些。我需要继续尝试来完全理解为什么这是预期的行为,但在此期间,我已经创建了一个带有密钥的示例,它按照我预期的方式工作,以防将来有人遇到这个问题:https://codesandbox.io/s/inspiring-nash-coo4e
关闭问题。

mefy6pfw

mefy6pfw3#

重新打开这个问题。

我发现使用会改变的键似乎与useTransition不兼容。通过改变键的顺序,我可以使悬垂尾部折叠或使useTransition钩子按预期工作,但不能两者兼得。

当使用键时,SuspenseList tail="collapsed" 按预期工作,但useTransition不起作用。

https://codesandbox.io/s/solitary-darkness-oq5w6

当不使用键时,SuspenseList tail="collapsed" 不起作用。

https://codesandbox.io/s/awesome-brook-ykt49

是否有办法让SuspenseList tail="collapsed" revealOrder="forwards" 和 useTransition同时起作用?我一直在尝试实验,但似乎找不到一种不涉及hack的方法。

这是一个演示我期望行为的Codepen(通过添加另一个没有键的组件来更新资源时会挂起 - 当然不是可行的解决方案):

https://codesandbox.io/s/silly-chatelet-2ve09

mzaanser

mzaanser4#

你想要的体验是什么?
useTransition 是在等待前一个屏幕加载数据时使用的。
SuspenseList 是在其他页面上逐步显示内容时使用的。
你需要选择主要的体验。
有一个技巧,你可以在 Suspense 边界上设置 unstable_avoidThisBoundary={true}。在这种模式下,它们会阻止过渡直到超时。然而,它们也会触发外部回退以进行初始渲染。因此,它在初始渲染时不能与 SuspenseList 一起使用。然后你需要将其设置为 false。
然而,这是一个奇怪的组合。我建议你决定你想做什么。要么在加载时留在前一个页面,要么立即转到下一个页面并让它逐步加载。
另一种方法是删除标题周围的边界,并将其放在没有键的整个子树周围。这样,你就可以使用 useTransition 等待标题,然后逐步加载其余的内容。

jv4diomz

jv4diomz5#

我正在寻找的体验是在第一页加载时尝试保持在第一页,但在一段时间后转到新页面并逐步加载新页面 - 就像我在这个例子中创建的体验(通过使用一个非常丑陋的技巧):
https://codesandbox.io/s/silly-chatelet-2ve09
我认为这不是一个奇怪的组合。事实上,如果我尝试在一个状态改变导致页面重新渲染而没有使用useTransition的情况下实现SuspenseList,就像在这个例子中:https://codesandbox.io/s/inspiring-nash-coo4e - 控制台会给我以下警告:

Warning: App triggered a user-blocking update that suspended.

The fix is to split the update into multiple parts: a user-blocking update to provide immediate feedback, and another update that triggers the bulk of the changes.

Refer to the documentation for useTransition to learn how to implement this pattern.

如果使用SuspenseList逐步加载会被认为是替代使用过渡,那么在使用SuspenseList时也许应该删除这个警告。然而,我认为将SuspenseList和useTransition一起使用是有意义的,这样在快速的机器上,你可以等待当前页面加载新数据,过渡可以感觉更顺畅;在慢速的机器上,在useTransition超时结束后,新页面将以指定的顺序逐步加载,这样用户就不会永远等待着加载旋转器,也看不到东西以随机顺序加载。
我知道我可以只用一个Suspense组件包裹整个内容,在新过渡超时结束后让新页面一起渲染,但如果我的应用运行得足够慢,以至于在useTransition超时期间页面没有加载,那么这正是我想要用SuspenseList并让我的应用程序以可靠顺序逐步加载的情况。
你建议将整个子树放入带有ProfileDetails的Suspense Package 器中,这确实解决了这个问题:https://codesandbox.io/s/sleepy-sanderson-ys94s
然而,如果头部加载得非常快,useTransition钩子不会等待超时完全结束的时间来尝试在过渡到新页面之前加载剩余的数据:https://codesandbox.io/s/jolly-microservice-erusi
此外,我认为这种处理方式消除了SuspenseList提供的代码整洁性优势,而且这种方法在更复杂的页面或具有嵌套SuspenseLists的页面上会变得更混乱。
我认为关于如何使用useTransition我还有一些信息不清楚,我不理解为什么useTransition钩子只保留对存在于过渡之前的Suspense组件的状态,而不保留对作为过渡结果传递的新键的Suspense组件的状态。

相关问题