react使用hooks启用setInterval中state值不变的问题

使用useEffect在函数组件中启用定时器

function UseReducerTemplate(props){
  const [count, setCount] = useState(0);
  useEffect(() => {
    let id = setInterval(() => {
      setCount(count + 1);
    }, 1000);
    return () => clearInterval(id);
  }, []);
  return <h1>{count}</h1>;
};

由于需要启用定时器,而且防止变量刷新,需要将useEffect中的第二个参数设置为空数组,防止重复渲染生成计数器,以及清除计数器。此时在函数第一次render()的时候创建定时器。相当于class组件中的componentDidMount生命周期创建定时器。
存在问题:此时进行渲染后发现页面中当0变成1后页面保持不变,并且一直是1。
原因:当第二个参数为空时此时第一个函数中形成了闭包,此时count值成为了一个常量0,而读取不到外部count值的变化,此时第一个函数是一个独立函数,其内部的状态和外部无关

存在问题的修复方式

function UseReducerTemplate(props){
  const [count, setCount] = useState(0);
  useEffect(() => {
    let id = setInterval(() => {
      setCount(count + 1);
    }, 1000);
    return () => clearInterval(id);
  }, [count]);
  return <h1>{count}</h1>;
};

如果此时函数想要正常读取外部的count则需要将useState中count值传入第二个参数,但是此时会出现刚开始提到的问题,计数器在重复的挂载清除,会存在比较大的性能损耗,因此此种方式也是不可取的

在hooks使用规范上有提示到,hooks内部使用的到状态参数要传入到第二个参数数组中,即effect 函数中引用的每个值也应出现在依赖项数组中。

可用的修复方式1

function UseReducerTemplate(props){
  const [count, setCount] = useState(0);
  useEffect(() => {
    let id = setInterval(() => {
      setCount(count => count + 1);
    }, 1000);
    return () => clearInterval(id);
  }, []);
  return <h1>{count}</h1>;
};

由于setState()中还可以接受一个函数,setState(preState => { return newState }), 通过此种方式可以读取到上一次的state值,并在上一值的基础上进行更改, 函数返回方式在维护一个state对象时有较好的使用效果,例如:setUser((user) = > ({ …user, name: ‘Nathan’ }));

可用的修复方式2

function UseReducerTemplate(props){
    const [count, setCount] = useState(0);
    const countRef = useRef(count);
    useEffect(() =>{
      countRef.current = count;
    });
    useEffect(() => {
      let id = setInterval(() => {
        setCount(countRef.current + 1);
      }, 1000);
      return () => clearInterval(id);
    }, []);
    return <h1>{count}</h1>;
};

由于此处产生了闭包,导致函数内部count成为了一个常量,因此我们创建一个count值的引用,此处countRef是维护一个对象,由于hooks在函数中是顺序调用,因此每次count值修改后其内部的curent会更改为当前的count值,因此我们在setInterval中可以正确进行读取

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值