为什么 useLazyLoadQuery() 看起来像是阻塞并且会导致重新渲染?

问题描述 投票:0回答:1

我正在遵循 Relay 教程,这是第 3 步,如 https://relay.dev/docs/tutorial/queries-1/ 所示。经过我调试的代码是

export default function Newsfeed() {
  console.log("HERE 0")

  const data = useLazyLoadQuery(
    NewsfeedQuery,
    {}
  )

  console.log("HERE 1", JSON.stringify(data));

在 Google Chrome 的开发控制台中,我可以看到以下内容:

所以很奇怪:看起来它能够到达“HERE 0”,然后获取数据,就好像它正在阻塞I/O(网络获取)(术语阻塞I/O的意思是,就像以前,当我们执行 Unix 系统调用

read()
时,这个函数在完成读取任务之前永远不会返回,不像现在,我们执行 JavaScript
fetch()
并设置一个
then
处理程序和
fetch()
立即返回,而不从网络读取单个字节)
,然后再次重新渲染组件:请注意,它没有转到“HERE 1”,而是再次执行“HERE 0”,然后“这里 1 英寸。

这与 React 的工作方式非常不同。传统的 React 应用程序就像,

const [data, setData] = useState(null);

useEffect(() => { 
  // fetching data here
}, []);

return (
  <div>{
     data && ... // display the data
  }</div>
);

也就是说,它将转到函数末尾并且不显示任何内容,因为

data
为空。一旦
data
是由
setData
引起的,导致重新渲染,那么组件就会显示一些东西。所以它是运行两次才能完成该功能。

上面的

useLazyLoadQuery()
代码看起来不像“两次运行完成”。看起来它神奇地可以导致中间重新渲染。

其实看起来并不像是“懒”。看起来它正在努力工作(过去的阻塞 I/O 是怎样的)。

它是如何工作的?

reactjs relayjs react-relay
1个回答
0
投票

这是因为 Relay 使用 Suspense。从您链接的教程中:

Relay 使用 Suspense 显示加载指示器,直到数据可用。

当使用 Suspense 获取数据时(无论是抛出 Promise 还是使用新的

use
钩子),如果 React 需要一些尚未存在的数据,它将停止渲染(“挂起”)组件。 React 将显示最近的 Suspense 边界的
fallback
并在加载数据时重新渲染子树。

在您的情况下,

useLazyLoadQuery
在后台请求一些数据,Next.js 处理所有与 Suspense 相关的内容,因此这可能不太明显。但是如果你尝试在普通的 React 项目(即没有框架)中使用
useLazyLoadQuery
,你可能会从 React 中得到错误,因为它无法找到 Suspense 边界,除非你明确定义了一个边界。

我对 Suspense 的所有内容进行了一些挖掘,并在前段时间制作了文章,如果您对 Suspense 的工作原理感兴趣,这可能是一个很好的起点。

© www.soinside.com 2019 - 2024. All rights reserved.