关于javascript:官方答在React18中请求数据的正确姿势其他框架也适用

大家好,我卡颂。

一些同学喜爱在useEffect中申请初始数据,相似这样:

useEffect(() => {
  fetch(xxx).then(data => setState(data.json()))
}, [])

React18并不举荐这种形式。

这么写有什么问题?如果不举荐这种形式,那么举荐的形式是什么呢?

本文来看看Dan在reddit是如何答复上述问题的。

欢送退出人类高质量前端框架群,带飞

这是一个广泛的问题

除了React外,大部分以组件模式组织的前端框架,都有如下相似的API

  • effect
  • didMount/didUpdate

如果有初始化时申请数据的需要,这类框架都会抉择在上述回调函数内执行申请操作,并在数据返回后更新状态。

所以,这并不是React独有的问题。相同,他很广泛。

之所以在React中这么突出,是因为React官网在疏导开发者不要用这种模式书写代码(通过严格模式下useEffect执行两次放大这个问题)。

React之所以这么做,是为了我的项目的性能以及UX(User Experience,用户体验)。

上面咱们来细聊这么做的影响。留神,这些影响同样实用于其余框架。

为什么不举荐这么写?

须要解决竞态问题

useEffect中申请数据要面临的第一个问题是须要解决竞态问题

假如你有个组件User,接管userID作为props,用userID申请数据后展现用户信息。

上面是你的写法:

function User({userID}) {
  const [data, setData] = useState(null);

  useEffect(() => {
    const res = await fetch(`https://xxx/${userID}/`);
    setData(res.json());
  }, [userID]);

  if (data) {
    return <div>{data.name}</div>;
  } 
  return null;
}

这里有个开发阶段很难复现的bug —— 如果userID变动足够快,会发动多个不同的用户申请。

而最终展现哪个用户的数据,取决于哪个申请先返回。这就是申请的竞态问题

点击返回按钮后从新申请数据

如果用户跳转到新的页面后,又通过浏览器回退按钮回到以后页面,并不能立即看到他跳转前的页面。

相同,看到的可能是个白屏 —— 因为还须要从新执行useEffect获取初始数据。

这个问题的实质起因是:没有初始数据的缓存。

CSR时的白屏工夫

CSR(Client-Side Rendering,客户端渲染)时在useEffect中申请数据,在数据返回前页面都是白屏状态。

瀑布问题

如果父子组件都依赖useEffect获取初始数据渲染,那么整个渲染流程如下:

  1. 父组件mount
  2. 父组件useEffect执行,申请数据
  3. 数据返回后从新渲染父组件
  4. 子组件mount
  5. 子组件useEffect执行,申请数据
  6. 数据返回后从新渲染子组件

可见,当父组件数据申请胜利后子组件甚至还没开始首屏渲染。

这就是渲染中的瀑布问题 —— 数据像瀑布一样一级一级向下流动,流到的组件才开始渲染,很低效。

既然间接写useEffect有这么多问题,那么举荐的形式是什么呢?

举荐的形式

Meta公司外部,基于Relay驱动数据(但申请数据要求应用GraphQL),所以这套架构比拟难在社区遍及开。

然而,当初社区曾经有了成熟的申请数据的计划

对于SSR,能够应用Next.jsRemix接管数据申请。

对于CSR,能够应用React QueryuseSWR接管数据申请。

这些成熟的计划都致力于解决上述提到的问题。

如果不想应用这些计划,想本人写,能够参考React新文档中上面两篇文章:

  • 应用effect同步数据
  • 你可能不须要应用effect

想看中文的同学,能够看我写的总结 —— React新文档:不要滥用effect哦

总结

本文咱们聊了React18之后不举荐的申请数据的形式以及举荐的申请数据的形式。

其中不举荐的申请数据的形式不仅存在于React中,很多前端框架都有这样的问题。

【腾讯云】云产品限时秒杀,爆款1核2G云服务器,首年50元

阿里云限时活动-2核2G-5M带宽-60G SSD-1000G月流量 ,特惠价99元/年(原价1234.2元/年,可以直接买3年),速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

您可能还喜欢...

发表回复

您的电子邮箱地址不会被公开。

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据