两种情况 两种原因
- 情况1:直接写在函数组件里:函数组件调用
setCount
值后,会重新执行函数组件,会形成新的闭包,每个闭包中的count
值都是相互独立的,此时拿不到上一次闭包中的count
值。 - 情况2:写在
useEffect
函数里:useEffect
如果没有设置依赖项的话,修改值后不会再执行,useEffect
只会在组件第一次渲染的时候执行。
class
组件就不会有这种问题,因为class
组件都是在this
的上下文中改变count
的值的,不会形成隔离的闭包。
解决方法两个:
1. 情况1:useRef
创建ref后,将值赋值给它,获取的时候都是获取的同一个对象下的current
值。
import React, { useState, useRef } from "react";
const Demo2 = () => {
let [count, setCount] = useState(0);
// useRef 返回的是同一个对象,类似 {current:''}
const countRef = useRef();
countRef.current = count;
const addCount = () => {
setCount(count + 1);
};
const alertCount = () => {count
setTimeout(() => {
alert(countRef.current);
}, 3000);
};
return (
<div>
<button onClick={addCount}>add Count</button>
<button onClick={alertCount}>alertCount</button>
<div>count: {count}</div>
</div>
);
};
export default Demo2;
如果不使用
useState
设置值(只是定义一个变量let count = 1;
),直接使用count = count + 1;
修改值。不使用setCount
修改值,那么每次取到的也是最新的count
,因为不使用setCount
函数组件就不会去更新,始终就是同一个闭包,因此也就取的是同一个值。
2. 情况2:useEffect
设置第二个参数依赖项
设置useEffect
的第二个参数依赖项,这个是一个数组类型的参数,将依赖项传入,依赖项的值发生改变后,会重新执行useEffect
,拿到最新的值。
如果里面写了定时器,最好return
出去一个函数里清除定时器。如果是addEventListener
监听事件,那么就return
一个函数清除监听事件。