开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第8天,点击查看活动详情
问题:
在下面的代码中定时器没有获取到最新的state
定时器中的count会一直都是0
因为定时器一直引用着旧的变量count
这也是闭包引起的问题
其实也可以侧面反映出useState返回的state并不是同一个引用
function App() {
const [count, setCount] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
// 下面的count 会一直为0,因为定时器一直引用着旧的变量。
//
console.log(count);
setCount(precount => precount + 1);
}, 1000);
return () => {
clearInterval(timer);
};
}, []);
return <div className="App">{count}</div>;
}
闭包
闭包是什么大家肯定都知道了,就是对函数作用域的引用,在函数外部可以访问到函数作用域,比如下面
这个例子
module函数返回了一个新的函数,当我们调用返回的函数export就可以得到module函数里面的变量了
这也是js模块化的实现方式之一
function module() {
const a = 1
return function () {
return a
};
}
const export = module()
const res = export() // a
解决
那么知道问题,就很好解决了 我们可以使用useRef来创建一个引用,只要state更新,就去更新引用的值,这样,在setInterval的函数内就可以保持一个引用,而获取到最新的值了
function App() {
const [count, setCount] = useState(0);
const countRef = useRef(null);
useEffect(() => {
// 更新引用值,
countRef.current = count;
}, [count])
useEffect(() => {
const timer = setInterval(() => {
// 这里的引用值会定期更新
console.log(count, countRef.current, " == count, countRef.current");
setCount(precount => precount + 1);
}, 1000);
return () => {
clearInterval(timer);
};
}, []);
return <div className="App">{count}</div>;
}
提取hook
我们可以把上面的代码封装成一个hook,叫useRefState
function useRefState(initialState) {
const [state, setState] = useState(initialState);
const stateRef = useRef(null);
useEffect(() => {
stateRef.current = state;
}, [state]);
return [state, setState, stateRef]; // 喜欢的话也可以返回具名的键值对 {state ...}
}
function App() {
const [count, setCount, countRef] = useRefState(0);
useEffect(() => {
const timer = setInterval(() => {
// 这里的引用值会定期更新
console.log(count, countRef.current, " == count, countRef.current");
setCount(precount => precount + 1);
}, 1000);
return () => {
clearInterval(timer);
};
}, []);
return <div className="App">{count}</div>;
}
代码来源自己的博客 github.com/lulusir/my-…
其他文章
在线等,后端悄悄改了接口文档被我抓住了怎么办?
和后端对线 | 前端如何保存base64字符串为文件
释放生产力 | Yapi,swagger2,swagger3生成请求代码
什么?在React中也可以使用vue响应式状态管理
clean-js | 在hooks的时代下,使用class管理你的状态
clean-js | 手把手教你写一个羊了个羊麻将版
有没有一种可能,你从来都没有真正理解async