为什么useEffect不适合API调用有些人喜欢,有些人不喜欢。 如果你不是来自React世界,这肯定听起来很奇怪,因为它的默认行为是可怕的“无限渲染循环”,这很容易遇到。例如:useEffect(()=>{console.log("HelloWorld")})看起来不错,对吧? 不,这会在每次渲染时打印“HelloWorld”,React开发模式OCD我迫不及待地想把结果放在第二个参数的依赖数组中,像这样:useEffect(()=>{console.log("HelloWorld")},[])所以我们必须始终手动确保你每次使用它时不会陷入死循环。 就是这样,我们修复了它,上面的代码应该只运行一次,对吧? 从技术上讲,但并不总是...严格模式问题 在开发模式下,如果您想享受React严格模式的好处,实际上会被调用两次。您已经知道为什么这是一个问题。以下面的代码为例:useEffect(()=>{api.post("/view",{})},[]) 假设我们有一个代码发送一个事件说用户像上面查看了类似useEffect的页面。在严格模式下,React会运行effect两次并发送一个double事件。 你可以让hacky参考像这样工作:exportdefaultfunctionuseEffectOnce(fn:()=>void){useEffect(()=>{if(ref.current){fn();}return()=>{ref.current=true;};},[fn]);} 但本质上,这是一个问题,至少不是一个优雅的解决方案。性能问题 根据官方文档,useEffect钩子在整个UI或组件渲染完成后运行。因此,当我们在其中放置一个API调用时,API调用将在UI完全完成渲染后开始,如下所示: 这不是最优的,因为虽然反应很快,但渲染UI总是需要一些时间,它会延迟我们的API调用,也可以在渲染开始时运行。 因此,更好的方法是获取数据并并行渲染。 我们是怎么做到的?React查询解决 React查询和我们讨论的完全一样,像useQuery这样的hooks会在渲染开始的时候立即获取数据,这样就不用等待React加载整个组件了,如下所示:这里是一个例子://withreactqueryconst{status,data,error,isFetching}=useQuery(['data'],async()=>{constdata=await(awaitfetch(`${API_BASE_URL}/data`).json()返回数据})//没有反应).json();setData(data);})();}catch(error){setError(error);}finally{setLoading(false);}},[]); 通过查看语法,我们可以看到reactquery不仅在页面加载时立即执行查询,而且在reactquery返回的单个对象中处理加载状态,错误状态和实际数据等许多事情。 此外,重新运行/使查询无效也很简单,如下所示。queryClient.invalidateQueries(['data'])其他一些著名的库也解决了这些问题,例如SWR、URQL和ApolloClient。 解决这个问题的另一种方法是实现SSR,以便数据先在后端呈现,或者使用像react-routerloaders这样的功能。结论 API对useEffects的调用可能容易出错或非常慢。因此,除非万不得已,否则最好避免使用它。同时建议大家使用一些库来处理数据的获取是比较合适的。译者简介 涂成业,社区编辑,信息系统项目经理,信息系统主管,PMP,某省综合评标专家,15年开发经验。多关注项目管理、前后端开发、微服务、架构设计、物联网、大数据等。 原文链接:https://articles.wesionary.team/why-useeffect-is-a-bad-place-to-make-api-calls-98a606735c1c
