资讯专栏INFORMATION COLUMN

解析React useEffect不支持async function示例

3403771864 / 441人阅读

  useEffect是很常见的,现在写的是十分需求的。

  useEffect(async()=>{ 
  awaitgetPoiInfo();//请求数据
   },[]);

  可是React 却无法支持这样做,就是因为 effect function 应该返回一个销毁函数(effect:是指return返回的cleanup函数),如果 useEffect 第一个参数传入 async,返回值则变成了 Promise,会导致 react 在调用销毁函数的时候报错 :function.apply is undefined。

  React为什么这么设计呢?

  1、useEffect 的返回值是要在卸载组件时调用的,React 需要在 mount 的这样才可以获取值。

  2、useEffect() 似乎有个潜在逻辑:第二次触发 useEffect 里的回调前,前一次触发的行为都执行完成,返回的清理函数也执行完成。这样逻辑才清楚。而如果是异步的,情况会变得很复杂,可能会很容易写出有 bug 的代码。

  下面有两种改进的方法大家可以参考下:

  简单改造

  1、简单改造的写法(不推荐)

  第一种 在内部创建一个异步函数anyNameFunction,之后就是等待,在后来就是调用setData

  可也有一个问题要知道,就是在asyncFunction请求有依赖外部的参数,不更新requestData 的 effect 的依赖,effect 就不会同步 props 和 state 带来的变更,也就不回重新请求数据

  useEffect(() => {
  // Create an scoped async function in the hook
  // 注意如果函数没有使用组件内的任何值,可以把它提到组件外面去定义
  // 下面代码可以提到外面,可以自由地在 effect 中使用,下面就不改啦
  async function asyncFunction() {
  await requestData();
  setData(data)
  }
  // Execute the created function directly
  anyNameFunction();
  }, []); // 这里设置成[]数组,因为我们只想在挂载的时候运行它一次

  或者 useEffect中异步函数采用IIFE写法( Immediately Invoked Function Expression即立即调用的函数式表达式)

  useEffect(() => {
  // Using an IIFE
  (async function anyNameFunction() {
  await requestData();
  })();
  }, []);

  2、把异步提取成多带带函数或自定义hook(推荐)

  第一种自定义 hook包裹,然后再effect中通过promise.then调用(github上大佬给的答案:github)

  // 自定义hook
  function useAsyncEffect(effect: () => Promise<void | (() => void)>, dependencies?: any[]) {
  return useEffect(() => {
  const cleanupPromise = effect()
  return () => { cleanupPromise.then(cleanup => cleanup && cleanup()) }
  }, dependencies)
  }
  // 使用
  useAsyncEffect(async () => {
  const count = await fetchData()
  setCount(count)
  }, [fetchData])

  或者利用useCallback 包装成hook

  useCallback 本质上是添加了一层依赖检查,使用useCallback,函数完全可以参与到数据流中,可以说如果一个函数的输入改变了,这个函数就改变了,如果没有,函数也不会改变。

  下面的例子中会依赖 type ,如果 type 保持不变,requestData 也会保持不变,effect 也不会重新运行,但是如果 type 修改了,requestData 也会随之改变,因此会重新请求数据。 

 // 封装
  const requestData = useCallback(async () => {
  changeLoading(true);
  changeError(false);
  changeList([]);
  requestAPI.getFeature({ type }).then((data) => {
  if (data) {
  changeList(data);
  }
  }).catch((e) => {
  changeError(true);
  }).finally(() => {
  changeLoading(false);
  });
  }, [type]); // type改变会重新生成函数
  // 普通接口请求
  useEffect(() => {
  requestData();
  }, [requestData]);
  // 多带带处理外层刷新的接口请求
  // refreshing是props传递的过来的,不应该与state状态改变混在一起,这也是hook的优势,将不相关的状态逻辑拆分成更细粒度
  useEffect(() => {
  if (!refreshing) {
  return;
  }
  requestData().then(() => {
  getRefreshStatus(false);
  });
  }, [refreshing]);

  今天讲到这里,后面更多精彩内容欢迎观看。


文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/128370.html

相关文章

  • React Hooks 中如何请求数据?

    摘要:现在,请求数据和查询参数两个相互独立,但是我们需要像一个办法希望他们耦合起来,只获取输入框输入的参数指定的话题文章。好了,现在一旦你改变输入框内容,数据就会重新获取。 showImg(https://segmentfault.com/img/remote/1460000018652592?w=1024&h=683); 通过这个教程,我想告诉你在 React 中如何使用 state 和 ...

    snowell 评论0 收藏0
  • React Hooks 入门(2019)

    摘要:到目前为止,表达这种流程的基本形式是课程。按钮依次响应并更改获取更新的文本。事实证明不能从返回一个。可以在组件中使用本地状态,而无需使用类。替换了提供统一,和。另一方面,跟踪中的状态变化确实很难。 备注:为了保证的可读性,本文采用意译而非直译。 在这个 React钩子 教程中,你将学习如何使用 React钩子,它们是什么,以及我们为什么这样做! showImg(https://segm...

    GitCafe 评论0 收藏0
  • useEffect支持async及await如何运用

    背景  在使用useEffect中用啦回调函数中使用 async...await... 这时候就会报错。  上面代码可以看到,在报错,effect function 应该返回一个销毁函数(effect:是指return返回的cleanup函数),如果 useEffect 第一个参数传入 async,返回值则变成了 Promise,结果就是会导致 react 在调用销毁函数的时候报错。  React...

    3403771864 评论0 收藏0
  • 「每日一瞥

    摘要:首先,我们需要一个基本框架来处理表单域变化和表格提交。最起码我们需要提供一个来告诉如果用户还没有对表单域进行改动,就不必展示错误。我们需要一个来标识用户已尝试提交表单,还需要来标识表单是否正在提交以及每个表单域是否正在进行异步校验。 showImg(https://segmentfault.com/img/remote/1460000017516912?w=1200&h=630); ...

    XboxYan 评论0 收藏0
  • 【译】如何在React Hooks中获取数据?

    摘要:在这种情况下,如果状态发生变化,将再次运行以从获取数据。你可以在内做到在表单中获取数据到目前为止,我们只有和按钮的组合。现在,在获取数据时,可以使用向函数发送信息。例如,在成功请求的情况下,用于设置新状态对象的数据。 原文链接: https://www.robinwieruch.de/r... 在本教程中,我想通过state和effect hook来像你展示如何用React Hook...

    habren 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<