我正在开发与 MobX 存储配合使用的组件,遇到了一个问题。当我转到具有不同项目 ID 的页面时,在加载数据后,我在渲染新数据之前看到了之前的数据。因此,我为第一次渲染编写了这个检查,这似乎对准备渲染组件很有用,但在我看来,这可能是错误的代码。是这样吗?
"use client"
const Component = (props) => {
const isFirstRender = useRef(true)
if (isFirstRender.current) {
/* some action */
isFirstRender.current = false
}
return (
/* some jsx */
)
})
这可能与此处记录的场景相同,当 prop 发生变化时重置所有状态
下面讨论与该问题相关的一些观点。
现在来谈谈这个问题:
现在这篇文章寻求一个解决方案来避免在每次 useEffect 之前总是发生的陈旧或过时的渲染,这与我们在上面的第 7 点中讨论过的观点完全相同。
一些可能解决方案的背景信息
请注意,组件将在渲染之间保留状态。这意味着通常当函数对象终止其调用时,函数对象内声明的所有变量都将丢失。当再次调用同一函数时,将重新创建相同的变量。这意味着函数的本地变量始终会被重置。
但是 React 函数式对象具有在渲染之间保留状态值的能力。React 默认的状态保留规则是,只要同一个组件在 UI 渲染树中的相同位置渲染,它就会保留状态。有关更多信息,可以阅读此处保留和重置状态。
虽然默认行为适合大多数用例,因此它已成为 React 的默认行为,但我们现在所处的环境并不适合这种行为。我们不希望 React 保留先前的 fetch。
这意味着我们需要一种方法来告诉 React,请随着 props 的变化重置状态。请注意,即使我们成功地随着 props 的变化重置状态,渲染过程和 useEffect 仍将以相同的正常顺序运行。将有一个具有最新状态的初始渲染和一个作为渲染后续运行的 useEffect。然而,我们可以在这里实现的改进是,这个初始渲染将始终与我们传递给 useState 的初始值一起使用。由于这个初始值是固定的,因此我们可以使用它来构建条件渲染 -加载状态或获取数据。
下面两个示例代码,演示相同。
下面的第一个代码演示了我们一直在讨论的问题。
应用程序.js
试运行
测试计划:点击按钮改变contentId
点击前的 UI
点击后,UI 仅持续不到 2 秒
观察
之前的数据保留时间不到 2 秒,这不是理想的 UI。UI 应该发生变化,以通知用户数据正在加载。2 秒后,模拟数据应该进入 UI。
下面的第二段代码解决了这个问题。除了属性键的使用方式不同之外,此代码与第一段代码相同。
它通过使用属性key来解决这个问题。此属性在状态保留方案中具有重要意义。有关更多信息,可以阅读此处保留和重置状态。
简而言之,现在发生的情况是,如果键在两次渲染之间发生变化,React 将重置状态。
App.js
试运行
测试计划:点击按钮改变contentId
点击前的 UI
点击后,UI 停留时间不到 2 秒
几秒后的 UI
观察
之前的数据没有保留,相反,IU 显示加载状态,并在实际数据到达后立即更新。这可能是此用例所需的 UI。
引用
当子项有条件渲染时,React 如何确定应用哪种状态?