【问题标题】:clearInterval() doesn't clear interval in ReactclearInterval() 不会清除 React 中的间隔
【发布时间】:2023-02-20 00:26:04
【问题描述】:

我想使用以下代码每 200 毫秒增加一次用户数,直到 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>)}

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    我建议你返回一个清理函数,这样你就不会在 StrictMode 中使用 React 18 时注册两次间隔,并且在组件卸载时将其从内存中删除。

    还可以使用 refuseRef 以及单独的 useEffect 来观察 users 的变化并清除那里的间隔。像这样:

    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>;
    };
    

    【讨论】:

      【解决方案2】:

      这不起作用,因为:

      • 您永远不会再次调用 useEffect 来检查条件是否满足
      • 间隔参考丢失

      我在这里制作了您的代码的工作示例:https://codepen.io/aSH-uncover/pen/wvmYdNy

      另外,您应该通过在创建间隔的挂钩中返回 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>)
      }
      

      【讨论】:

        【解决方案3】:

        我想到了这个。你可以试试看。虽然上面推荐了很多方法

         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);
            }
          }, []);
        

        【讨论】:

          【解决方案4】:

          您检查条件 users &gt;= 5000 的方式不起作用,因为 users 未在您的 useEffect 挂钩中列为依赖项。因此当 users 改变时,钩子只运行一次但不会再次运行。因此,您只在开始时检查一次40 &gt;= 5000

          没有 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>
          }
          

          【讨论】:

            猜你喜欢
            • 2021-07-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-03-14
            相关资源
            最近更新 更多