简体   繁体   English

clearInterval() 不清除 React 中的间隔

[英]clearInterval() doesn't clear interval in React

I want to increment the number of users after each 200ms till 5000 with the below code.我想使用下面的代码在每 200 毫秒后增加用户数,直到 5000。 But it doesn't clear the interval when the number of users greater than 5000.但是当用户数大于 5000 时,它不会清除间隔。

const Cards = () => {
const [users, setUsers] = useState(40);

useEffect(() => {
    const setIntervalUsers = setInterval(() => {
        setUsers((prevUsers) => prevUsers = prevUsers + 100)
    }, 200);

    if (users >= 5000) {
        console.log('ok');
        clearInterval(setIntervalUsers)
    }
}, []);


return (<div>number of users {users} </div>)}

I would suggest you to return a clean up function so you don't register the interval twice in case you are in StrictMode with React 18, and also to remove it from the memory when the component gets unmounted.我建议你返回一个清理 function 这样你就不要注册间隔两次,以防你在 React 18 的StrictMode下,并且在组件被卸载时从 memory 中删除它。

Also use a ref sets with useRef and a separate useEffect that would watch changes in users and clear the interval there.还可以使用带有useRefref集和单独的useEffect来观察users的变化并清除那里的间隔。 Like so:像这样:

import { useEffect, useRef, useState } from "react";
const Cards = () => {
  const [users, setUsers] = useState(40);
  const intervalRef = useRef();

  useEffect(() => {
    if (users >= 5000) {
      console.log("ok");
      clearInterval(intervalRef.current);
    }
  }, [users]);

  useEffect(() => {
    intervalRef.current = setInterval(() => {
      setUsers((prevUsers) => (prevUsers = prevUsers + 100));
    }, 200);
    return () => clearInterval(intervalRef.current);
  }, []);

  return <div>number of users {users} </div>;
};

The way how you check for your condition users >= 5000 is not working because users is not listed as a dependency in your useEffect hook.检查条件users >= 5000的方式不起作用,因为users未在useEffect挂钩中列为依赖项。 Therefore the hook only runs once but doesnt run again when users change.因此,钩子只运行一次,但在users更改时不会再次运行。 Because of that you only check for 40 >= 5000 once at the beginning.因此,您只在开始时检查40 >= 5000一次。

An easier way to handle that is without a setInterval way.一种更简单的处理方法是没有setInterval方式。

export const Cards = () => {
  const [users, setUsers] = useState(40);
  
  useEffect(() => {
    // your break condition
    if (users >= 5000) return;
    
    const increment = async () => {
      // your interval
      await new Promise((resolve) => setTimeout(resolve, 200));
      setUsers((prevState) => prevState + 100);
    }
    
    // call your callback
    increment();
    
    // make the function run when users change.
  }, [users]);
  
  return <p>current number of users {users}</p>
}

This doesnt work because:这不起作用,因为:

  • you never call the useEffect again to check if the condition is met你永远不会再次调用 useEffect 来检查条件是否满足
  • the interval ref is lost间隔参考丢失

I made a working sample of your code here: https://codepen.io/aSH-uncover/pen/wvmYdNy我在这里制作了您的代码的工作示例: https://codepen.io/aSH-uncover/pen/wvmYdNy

Addintionnaly you should clean the interval when the component is destroyed by returning the cleanInterval call in the hook that created the inteerval此外,您应该通过在创建间隔的钩子中返回 cleanInterval 调用来清除组件被销毁时的间隔

const Card = ({ step }) => {
  const intervals = useRef({})
  
  const [users, setUsers] = useState(40)
  
  useEffect(() => {
    intervals.users = setInterval(() => {
      setUsers((prevUsers) => prevUsers = prevUsers + step)
    }, 200)
    return () => clearInterval(intervals.users)
  }, [])
  
  useEffect(() => {
    if (users >= 5000) {
        clearInterval(intervals.users)
    }
  }, [users])
  
  return (<div>number of users {users} </div>)
}

I came up with this.我想出了这个。 You can try it out.你可以试试看。 Although there are many ways suggested above虽然上面推荐了很多方法

 const [users, setUsers] = useState(40);
 const [max_user, setMaxUser] = useState(true);

  let setIntervalUsers: any;
  let sprevUsers = 0;
  useEffect(() => {
    if (max_user) {
      setIntervalUsers = setInterval(() => {
        sprevUsers += 100;
        if (sprevUsers >= 5000) {
          setMaxUser(false);
          clearInterval(setIntervalUsers);
        } else {
          setUsers(sprevUsers);
        }
      }, 200);
    }
  }, []);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM