在 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)
我有一个正在过渡的文本数组,当我到达结尾时它循环回到 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)