React 2024 年 3 月 21 日
react(四)-hooks闭包陷阱
react(四)-hooks闭包陷阱
react(四)-hooks闭包陷阱及原因
怎么产生闭包的
import React, {useEffect, useState} from 'react';
function App() {
const [count, setCount] = useState(0)
useEffect(() => {
setInterval(() => {
console.log('count', count)
setCount(count + 1)
},2e3)
}, [])
return (
<div>{count}</div>
);
}
export default App;
setCount(count + 1)依赖的是count,而count引用的是当时的count,也就是初始值0的时候,所以count永远是0,setCount(count + 1)永远是setCount(0 + 1)
useReducer来解决闭包陷阱
import {useReducer,Reducer,useEffect} from "react";
interface Action{
type:'add' | 'minus';
num:number;
}
function reducer(state:number,action:Action){
switch(action.type){
case 'add':
return state + action.num;
case 'minus':
return state - action.num;
default:
return state;
}
}
function App (){
/**
* useReducer返回两个参数
* state:当前状态
* dispatch:dispatch方法
* useReducer接收一个reducer函数和初始状态
* Reducer<number, Action>是ts的类型声明,表明reducer函数的参数是number和Action类型
*/
const [state,dispatch] = useReducer<Reducer<number, Action>>(reducer,1000)
useEffect(() => {
const interval = setInterval(() => {
dispatch({type:'minus',num:7}) // 1000 减 7 等于多少
},1000);
return () => { // 清除定时器
clearInterval(interval);
}
}, []);
return (
<div>
{state}
</div>
)
}
export default App;
useState解决闭包陷阱
import {useEffect, useState} from "react";
function App() {
const [count, setCount] = useState(0)
useEffect(() => {
console.log(count)
const interval = setInterval(() => {
// 使用函数式更新,这样就不依赖于外部的 `count` 变量
setCount(count => count + 1)
}, 1000)
return () => {
clearInterval(interval)
}
}, []);
return (
<div>{count}</div>
)
}
export default App;
这里的console.log(count)始终都是0。因为引用的是声明变量时候的初始值0。
所以修改deps数组为count,count变化的时候重新执行useEffect,执行的函数就引用的是最新的count值。
版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
作者: 保安 发表日期:2024 年 3 月 21 日