当前位置: 首页 > Web前端 > vue.js

官方解答:React18中请求数据的正确姿势(其他框架也适用)

时间:2023-03-31 21:07:22 vue.js

大家好,我是凯森。有些同学喜欢在useEffect中请求初始数据,像这样:useEffect(()=>{fetch(xxx).then(data=>setState(data.json()))},[])但是React18不推荐这样方式。这样写有什么问题?如果这不是推荐的方式,那么推荐的方式是什么?本文来看看Dan在reddit上是如何回答上述问题的。欢迎加入人类优质前端框架群。这是一个常见问题。除了React,大多数以组件形式组织起来的前端框架都有类似如下的API:effectdidMount/didUpdate如果在初始化时有请求数据的需求,这类框架会选择在上面的回调函数内部进行请求操作并在数据返回后更新状态。所以,这不是React独有的问题。相反,他是普世的。之所以在React中如此突出,是因为React官方在引导开发者不要写这种形式的代码(严格模式下两次执行useEffect会放大这个问题)。React之所以这样做,是为了项目的性能和UX(UserExperience,用户体验)。让我们详细谈谈这方面的影响。请注意,这些影响也适用于其他框架。为什么不建议这样写呢?需要解决竞态问题在useEffect中请求数据时,你面临的第一个问题就是需要解决竞态问题。假设您有一个组件User,它接收userID作为props,并在使用userID请求数据后显示用户信息。写法如下:functionUser({userID}){const[data,setData]=useState(null);useEffect(()=>{constres=awaitfetch(`https://xxx/${userID}/`);setData(res.json());},[userID]);如果(数据){return

{data.name}
;}returnnull;}这里有一个开发阶段难以重现的bug——如果userID变化足够快,就会发起多个不同的用户请求。最终显示哪个用户的数据取决于先返回哪个请求。这是请求的竞争条件。点击后退按钮后重新请求数据如果用户跳转到新页面,通过浏览器后退按钮返回当前页面,则无法立即看到跳转前的页面。相反,您看到的可能是白屏——因为您需要重新执行useEffect才能获取初始数据。这个问题的本质原因是:没有缓存初始数据。CSR期间的白屏时间CSR(Client-SideRendering,客户端渲染)在useEffect中请求数据时,在返回数据之前页面处于白屏状态。瀑布问题如果父子组件都依赖useEffect获取初始数据渲染,那么整个渲染过程如下:父组件挂载父组件useEffect执行,请求数据数据返回然后重新渲染父组件子组件挂载子组件useEffect执行,请求数据返回,重新渲染渲染子组件可见。当父组件数据请求成功时,子组件甚至还没有开始首屏渲染。这就是渲染中的瀑布问题——数据像瀑布一样一层一层往下流,流向它的组件开始渲染,效率很低。既然直接写useEffect问题那么多,那有什么推荐的方式呢?推荐的方式是在Meta公司内部,基于Relay驱动数据(但是请求数据需要使用GraphQL),所以这种架构很难在社区普及。但是,现在社区已经有了成熟的请求数据的解决方案。对于SSR,可以使用Next.js和Remix来接管数据请求。对于CSR,可以使用ReactQuery,使用SWR来接管数据请求。这些成熟的方案就是致力于解决上述问题。如果你不想使用这些解决方案,想自己写,可以参考React新文档中的以下两篇文章:使用effect同步数据你可能不需要使用effect想看中文的同学可以看我写的总结——Reactnewdocument:不要滥用效果哦总结在这篇文章中,我们讲了React18之后不推荐的请求数据方式和推荐的请求数据方式。不推荐的请求数据方式不仅存在于React中,在很多前端框架中也存在。