React 挂钩依赖项,包括它创建一个无限循环,不包括它不会给我最新的值

IT技术 reactjs react-hooks
2021-05-15 14:23:44

使用React hooks. 我正在尝试使用一些数据进行简单的 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("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>
  );
};

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

我需要的:

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

问题是:

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

我究竟做错了什么?

1个回答

由于您没有在其他任何地方使用 fetch 方法,因此将它useEffect直接放在里面是有意义的不需要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]);

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

您可以在官方文档中找到更多信息(查找“...在效果中移动该功能”):https : //reactjs.org/docs/hooks-faq.html#is-it-safe-to-从依赖项列表中省略函数

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

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