React 挂钩依赖项,包括它创建一个无限循环,不包括它不会给我最新的值 [英] React hooks dependencies, including it creates an infinite loop, not including it doesn't give me the latest value

查看:36
本文介绍了React 挂钩依赖项,包括它创建一个无限循环,不包括它不会给我最新的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 React 钩子.我正在尝试使用一些数据进行简单的 API 提取调用,但我似乎无法完成这项工作.这是沙盒链接

在此示例中,目标是每 5 秒向服务器获取自最新 latestUpdate 以来对用户名的任何更新.

但为了方便起见,我也会在这里包含代码:

const SmallComponent = () =>{const { id, username, latestUpdate } = useItemState();const dispatch = useItemDispatch();console.log("Render id", id, "Latest", latestUpdate);const fetchUsername = useCallback(async () => {console.log("获取 ID", id, "最新", 最新更新);const 响应 = 等待获取("https://jsonplaceholder.typicode.com/users/" + id);const user = await response.json();dispatch({ type: "setUsername", usernameUpdated: user.name });}, [调度, id]);const updateId = useCallback(() => {dispatch({ type: "setId", id: id + 1 });}, [调度, id]);useEffect(() => {取用户名();const refresh = setInterval(() => {更新 ID();}, 5000);返回 () =>清除间隔(刷新);}, [fetchUsername, updateId]);返回 (<div><h4>来自提取的用户名:</h4><p>{用户名||未设置"}

);};

您会注意到,我的 fetchUsername 缺少 latestUpdate 的依赖项(它在我的服务器上用于仅从该日期起发送 udpates).当 fetchUsername 在我的减速器中完成时,我更新 latestUpdate.

我需要什么:

  • 挂载时:获取用户名 => 更新用户名和最新更新的状态
  • 间隔:每 5 秒 => 获取用户名更新并将 latestUpdate 更新为 new Date()

问题是:

  • 如果我为 fetchUsername 添加依赖项到 useCallback,我会得到一个无限刷新循环.
  • 如果我不添加,我的latestUpdate值是错误的(即初始值)

我做错了什么?

解决方案

由于您没有在其他任何地方使用 fetch 方法,因此将其直接放在 useEffect 中是有意义的.不需要 useCallback:

 useEffect(() => {const fetchUsername = async() =>{console.log("FETCH", latestUpdate);常量网址 ="https://jsonplaceholder.typicode.com/users/" + id + "#" + latestUpdate;const 响应 = 等待 fetch(url);const user = await response.json();dispatch({ type: "setUsername", usernameUpdated: user.name });};const refresh = setInterval(() => {取用户名();}, 5000);返回 () =>清除间隔(刷新);}, [调度, id, 最新更新]);

这是完整的 CodeSandBox:https://codesandbox.io/s/trusting-framework-hvw06?file=/src/App.js

您可以在官方文档中找到更多信息(查找...将该函数移动到您的效果内"):https://reactjs.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies

而且我还推荐 Robin Wieruch 的钩子获取教程:https://www.robinwieruch.de/react-hooks-fetch-data

一般来说,我强烈推荐使用类似 react-query 的东西,因为它也会处理缓存.这是使用服务器数据的更好方法(而不是获取响应并将其放入上下文中):https://github.com/tannerlinsley/react-query

Using React hooks. I'm trying to do a simple API fetch call with some data, but I can't seem to make this work. Here is the sandbox link

In this example, the objective is that every 5secs, it fetches to the server to get any updates to the username since the latest latestUpdate.

But for convenience, I will include the code here as well:

const SmallComponent = () => {
  const { id, username, latestUpdate } = useItemState();
  const dispatch = useItemDispatch();

  console.log("Render id", id, "Latest", latestUpdate);

  const fetchUsername = useCallback(async () => {
    console.log("Getting Id", id, "Latest", latestUpdate);
    const response = await fetch(
      "https://jsonplaceholder.typicode.com/users/" + id
    );
    const user = await response.json();
    dispatch({ type: "setUsername", usernameUpdated: user.name });
  }, [dispatch, id]);

  const updateId = useCallback(() => {
    dispatch({ type: "setId", id: id + 1 });
  }, [dispatch, id]);

  useEffect(() => {
    fetchUsername();
    const refresh = setInterval(() => {
      updateId();
    }, 5000);

    return () => clearInterval(refresh);
  }, [fetchUsername, updateId]);

  return (
    <div>
      <h4>Username from fetch:</h4>
      <p>{username || "not set"}</p>
    </div>
  );
};

As you'll notice, my fetchUsername is missing a dependency for latestUpdate (which is used on my server to only send udpates since that date). I update latestUpdate when the fetchUsername is finished in my reducer.

What I need:

  • on mount: fetch username => updates state for username and latestUpdate
  • interval: every 5secs => fetch updates to username and update latestUpdate to new Date()

The problem is:

  • If I add the dependency to the useCallback for fetchUsername, I get an infinite refresh loop.
  • If I don't add it, my latestUpdate value is wrong (ie initial value)

What am I doing wrong?

解决方案

As you're not using the fetch method anywhere else, it makes sense to put it inside the useEffect directly. No need for useCallback:

  useEffect(() => {
    const fetchUsername = async () => {
      console.log("FETCH", latestUpdate);
      const url =
        "https://jsonplaceholder.typicode.com/users/" + id + "#" + latestUpdate;

      const response = await fetch(url);
      const user = await response.json();
      dispatch({ type: "setUsername", usernameUpdated: user.name });
    };

    const refresh = setInterval(() => {
      fetchUsername();
    }, 5000);

    return () => clearInterval(refresh);
  }, [dispatch, id, latestUpdate]);

Here is the full CodeSandBox: https://codesandbox.io/s/trusting-framework-hvw06?file=/src/App.js

You can find more in the official docs (look for "...to move that function inside of your effect"): https://reactjs.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies

And I also recommend Robin Wieruch's hook-fetching tutorial: https://www.robinwieruch.de/react-hooks-fetch-data

In general, I would highly recommend using something like react-query, as it will also take care of caching. It is a better way to consume your server data (instead of fetching and putting the response in your context): https://github.com/tannerlinsley/react-query

这篇关于React 挂钩依赖项,包括它创建一个无限循环,不包括它不会给我最新的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆