为了账号安全,请及时绑定邮箱和手机立即绑定

为什么我的计时器组件在将依赖项传递给 useEffect 时表现奇怪?

为什么我的计时器组件在将依赖项传递给 useEffect 时表现奇怪?

回首忆惘然 2023-09-28 17:46:21
我使用以下计时器useEffect并向其传递函数依赖项:const Timer = () => {  const [count, setCount] = useState(0);  const setId = () => {    const id = setInterval(() => {      setCount(count + 1);    }, 1000);    return () => clearInterval(id);  }  useEffect(() => {    setId();  }, [setId])}然而计时器的行为很奇怪:前几秒是正常的,然后它开始随机显示计数。是什么导致了这个问题?正确的做法是什么?
查看完整描述

3 回答

?
FFIVE

TA贡献1797条经验 获得超6个赞

afimport React, { useCallback, useState, useEffect, useRef } from "react";

import "./styles.css";


export default function App() {

  let [count, setCount] = useState(0);


  useInterval(() => {

    setCount(count + 1);

  }, 1000);


  return <div className="App">{count}</div>;

}


function useInterval(callback, delay) {

  const savedCallback = useRef();


  // Remember the latest callback.

  useEffect(() => {

    savedCallback.current = callback;

  }, [callback]);


  // Set up the interval.

  useEffect(() => {

    function tick() {

      savedCallback.current();

    }

    if (delay !== null) {

      let id = setInterval(tick, delay);

      return () => clearInterval(id);

    }

  }, [delay]);

}

工作代码沙箱

更新

正如 keith 建议的那样,不要将函数传递给数组 deps,如下所示。

import React, { useState, useEffect } from "react";

import "./styles.css";


export default function App() {

  const [count, setCount] = useState(0);


  useEffect(() => {

    const interval = setInterval(() => {

      setCount((count) => count + 1);

    }, 1000);


    return () => {

      clearInterval(interval);

    };

  }, []);


  return <div>{count}</div>;

}


查看完整回答
反对 回复 2023-09-28
?
守候你守候我

TA贡献1802条经验 获得超10个赞

还是不太清楚为什么可以通过[]

也许需要更多解释,不幸的是评论太多,所以我发布了这个。

要回答这个问题,我们需要退一步,首先问,依赖数组的意义是什么?简单的答案是 useEffect 中任何依赖于某些内容的内容,如果从需要不同处理的 useState 或 Props 进行更改,则需要将其放入数组中。

例如,如果您有一个仅显示用户配置文件的组件,但获取此信息是异步的,因此需要 useEffect。它可能看起来像这样 ->

<UserProfile userId={userId}/>

现在的问题是,如果我们[]作为依赖项传递,则 useEffect 不会为新的 userId 重新触发,因此 props 可能会说userId = 2,但我们当前存储在状态中的数据是 for userId = 1,.. 所以对于这样的东西[props.userId]完全有道理。

那么回到 OP 的组件,<App/>这里有什么会改变的?好吧,这不是道具,因为没有被传递。那么count您可能会问,我们再次问自己这个问题,计数状态是否保证 setInterval 的新实例被销毁/创建?当然,这里的答案是否定的,因此[]在这里传递是完全有意义的。

希望这是有道理的。


查看完整回答
反对 回复 2023-09-28
?
ABOUTYOU

TA贡献1812条经验 获得超5个赞

清除卸载时的间隔


useEffect(() => {

    let id;

    const setId = () => {

      id = setInterval(() => {

        setCount((count) => count + 1);

      }, 1000);

    };

    setId();

    return () => clearInterval(id);

  }, []);


查看完整回答
反对 回复 2023-09-28
  • 3 回答
  • 0 关注
  • 74 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信