在 React 中使用 UseEffect 时设置 Inverval 中断

Set Inverval breaks when using UseEffect in React

我有一个正在过渡的文本数组,当我到达结尾时它循环回到 0 并再次播放。第一次通过后一切正常,然后它失去同步并加速。关于如何解决这个问题有什么想法吗?

Codesanbox: https://codesandbox.io/s/text-show-forked-zqkvz

JS:

const Loader = (props) => {
  const { messages } = props;
  const [messageIndex, setMessageIndex] = useState(0);

  useEffect(() => {
    setInterval(() => {
      if (messageIndex === messages.length - 1) {
        setMessageIndex(0);
      } else {
        setMessageIndex(messageIndex + 1);
      }
    }, 2000);
  }, [messages, messageIndex]);

  return <div>{messages[messageIndex]}</div>;
};

export default function App() {
  return (
    <div className="App">
      <Loader messages={messages} />
    </div>
  );
}

在您的特定情况下,清除间隔就足够了:

  useEffect(() => {
    const interval = setInterval(() => {
      if (messageIndex === messages.length - 1) {
        setMessageIndex(0);
      } else {
        setMessageIndex(messageIndex + 1);
      }
    }, 2000);

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

但是,我建议您阅读 Dan Abramov 撰写的 article 关于工作 setInterval 和 React 钩子的文章。

TL;DR

您可以使用自定义挂钩:

import React, { useState, useEffect, useRef } from 'react';

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

所以你的 useEffect 应该是这样的:

    useInterval(() => {
      if (messageIndex === messages.length - 1) {
        setMessageIndex(0);
      } else {
        setMessageIndex(messageIndex + 1);
      }
    }, 2000)