我不明白为什么当我使用setTimeout函数时,我的react组件开始到infinite console.log。一切都在工作,但PC开始滞后的地狱。 有人说这个函数在超时时改变我的状态还有那个重新渲染组件,设置新定时器等等。现在我需要知道如何证明它是正确的。

export default function Loading() {
  // if data fetching is slow, after 1 sec i will show some loading animation
  const [showLoading, setShowLoading] = useState(true)
  let timer1 = setTimeout(() => setShowLoading(true), 1000)

  console.log('this message will render  every second')
  return 1
}

明确在不同版本的代码中没有帮助:

const [showLoading, setShowLoading] = useState(true)
  let timer1 = setTimeout(() => setShowLoading(true), 1000)
  useEffect(
    () => {
      return () => {
        clearTimeout(timer1)
      }
    },
    [showLoading]
  )

当前回答

您的计算机延迟是因为您可能忘记将空数组作为useEffect的第二个参数传递,并在回调中触发了setState。这将导致一个无限循环,因为useEffect在呈现时被触发。

下面是一个在挂载时设置定时器并在卸载时清空定时器的工作方法:

function App() { React.useEffect(() => { const timer = window.setInterval(() => { console.log('1 second has passed'); }, 1000); return () => { // Return callback to run on unmount. window.clearInterval(timer); }; }, []); // Pass in empty array to run useEffect only on mount. return ( <div> Timer Example </div> ); } ReactDOM.render( <div> <App /> </div>, document.querySelector("#app") ); <script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script> <div id="app"></div>

其他回答

如果你想创建一个类似“start”的按钮,那么使用“useInterval”钩子可能不合适,因为react不允许你调用组件顶部以外的钩子。

export default function Loading() {
  // if data fetching is slow, after 1 sec i will show some loading animation
  const [showLoading, setShowLoading] = useState(true)
  const interval = useRef();

  useEffect(() => {
      interval.current = () => setShowLoading(true);
  }, [showLoading]);

  // make a function like "Start"
  // const start = setInterval(interval.current(), 1000)

  setInterval(() => interval.current(), 1000);

  console.log('this message will render  every second')
  return 1
}

每10秒触发一次api:

useEffect(() => {
  const timer = window.setInterval(() => {
    // function of api call 
  }, 1000);

  return () => { 
    window.clearInterval(timer);
  }
}, [])

如有状态变化:

useEffect(() => {
  // add condition to state if needed
  const timer = window.setInterval(() => {
    // function of api call 
  }, 1000);

  return () => { 
    window.clearInterval(timer);
  }
}, [state])
const[seconds, setSeconds] = useState(300);

function TimeOut() {
useEffect(() => {
    let interval = setInterval(() => {
        setSeconds(seconds => seconds -1);
    }, 1000);

    return() => clearInterval(interval);
}, [])

function reset() {
  setSeconds(300); 
} 

return (
    <div>
        Count Down: {seconds} left
        <button className="button" onClick={reset}>
           Reset
        </button>
    </div>
)
}

确保导入useState和useEffect。另外,添加在0处停止计时器的逻辑。

您的计算机延迟是因为您可能忘记将空数组作为useEffect的第二个参数传递,并在回调中触发了setState。这将导致一个无限循环,因为useEffect在呈现时被触发。

下面是一个在挂载时设置定时器并在卸载时清空定时器的工作方法:

function App() { React.useEffect(() => { const timer = window.setInterval(() => { console.log('1 second has passed'); }, 1000); return () => { // Return callback to run on unmount. window.clearInterval(timer); }; }, []); // Pass in empty array to run useEffect only on mount. return ( <div> Timer Example </div> ); } ReactDOM.render( <div> <App /> </div>, document.querySelector("#app") ); <script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script> <div id="app"></div>

export const useTimeout = () => {
    const timeout = useRef();
    useEffect(
        () => () => {
            if (timeout.current) {
                clearTimeout(timeout.current);
                timeout.current = null;
            }
        },
        [],
    );
    return timeout;
};

您可以使用简单的钩子来共享超时逻辑。

const timeout = useTimeout();
timeout.current = setTimeout(your conditions)