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

1次阅读

共计 1640 个字符,预计需要花费 5 分钟才能阅读完成。

大家好,我卡颂。

一些同学喜爱在 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 中,很多前端框架都有这样的问题。

正文完
 0