-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
setInterval 在 useEffect 中 的 state 未更新 #4425
Comments
欢迎提交 Issue~ 如果你提交的是 bug 报告,请务必遵循 Issue 模板的规范,尽量用简洁的语言描述你的问题,最好能提供一个稳定简单的复现。🙏🙏🙏 如果你的信息提供过于模糊或不足,或者已经其他 issue 已经存在相关内容,你的 issue 有可能会被关闭。 Good luck and happy coding~ |
定时器 在hooks 不是这样用的,可以查找 react hooks setInterval |
@renshengwudi 非常感谢。 我去搜了 Dan 的这篇文章:https://overreacted.io/making-setinterval-declarative-with-react-hooks/#second-attempt 里面就提到了这个常犯的错误,是由于闭包引起的: 例子: function Counter() {
let [count, setCount] = useState(0);
useEffect(() => {
let id = setInterval(() => {
setCount(count + 1);
}, 1000);
return () => clearInterval(id);
}, []);
return <h1>{count}</h1>;
} 这里的
(但我还不是很能理解为什么这里会由于闭包呢?是和 解决方法之一,是把 但是我在 Taro 中使用碰到的上述问题里,确实是使用了这种 然后是关于 React 官方文档里用了 Dan 的那篇文章里也是用了 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]);
} 但在我看来,这也太「过度实现」了。之前有生命周期的 class 写法,反而更直观。或许也还是我思维还没转变过来, 那么咋办呢。最后,我还是选择了用 function Counter() {
let [count, setCount] = useState(0);
useEffect(() => {
let id = setTimeout(() => {
setCount(count + 1);
}, 1000);
return () => clearTimeout(id);
}, [count]);
return <h1>{count}</h1>;
}
|
并不是什么内部实现的问题,理解闭包的基本原理就可以理解,函数在哪里定义,就从此作用域开始往上寻找引用的变量而已。
你 setCount 用法是对的,但你直接用 ellipsis 进行判断: 解决办法很简单,用 useRef 保存最新的 ellipsis,判断时取出来判断。 function Index() {
const [ellipsis, setEllipsis] = useState('.')
const ellRef = useRef()
ellRef.current = ellipsis
useEffect(() => {
const timer = setInterval(() => {
console.log(ellRef.current)
if (ellRef.current.length === 6) {
setEllipsis('.')
} else {
setEllipsis(val => val + '.')
}
}, 1000)
return () => {
clearInterval(timer)
}
}, [])
return (
<div>
<div>{ellipsis}</div>
</div>
)
} |
Hello~ 您的问题楼上已经有了确切的回答,如果没有更多的问题这个 issue 将在 15 天后被自动关闭。 如果您在这 15 天中更新更多信息自动关闭的流程会自动取消,如有其他问题也可以发起新的 Issue。 Good luck and happy coding~ |
@Chen-jj @Songkeys 的确是由于 |
sorry,反复阅读了上面提到的dan的那篇文章,终于理解了:
|
效果是视图上会每 500ms 在省略号上多加一个
.
,但是 js 里 ellipsis 永远是.
,并没有更新到最新状态。The text was updated successfully, but these errors were encountered: