useEffect: 用于在组件渲染后执行一些操作,可以模拟 componentDidMount、componentDidUpdate 和 componentWillUnmount 生命周期
Copy const [number, setNumber] = useState(0);
// 没有依赖
useEffect(() => {
console.count("useEffect");
document.title = `You clicked ${number} times`;
},);
// 正确
useEffect(() => {
console.count("useEffect");
document.title = `You clicked ${number} times`;
}, [number]);
console.count("组件渲染!");
Copy const [state, setState] = useState({
name: "",
selected: false,
});
// useMemo相当于vue的计算属性
const user = useMemo(
() => ({
name: state.name,
selected: state.selected,
}),
[state.name, state.selected]
);
// 监听计算属性
useEffect(() => {
console.log(`user改变, useEffect`);
}, [user]);
// 理解watch成直接监听state属性
useEffect(() => {
console.log(`state改变, useEffect`);
}, [state.name, state.selected]);
Copy const [number, setNumber] = useState(0);
//没有一秒更新一次、没有清理定时器、
useEffect(() => {
console.log("useEffect")
setInterval(() => {
setNumber(number + 1);
}, [1000]);
}, [number]);
// 没有清除定时器,可能导致性能问题和内存泄漏问题
useEffect(() => {
console.log("useEffect")
setInterval(() => {
setNumber((prev) => prev + 1);
}, [1000]);
}, []);
//正确用法,number一更新就会重新
useEffect(() => {
console.log("useEffect 开始!");
const interval = setInterval(() => {
setNumber((prev) => prev + 1);
}, [1000]);
return () => { // 清理上一次useEffect
clearInterval(interval);
};
}, []);
console.count("组件渲染!");
// 结果 组件渲染! -》 useEffect 开始!(只执行一次) -》组件渲染!-》组件渲染!
return <div>{number}</div>;
Copy const [toggle, setToggle] = useState(false);
useEffect(() => {
console.log("effect执行");
return () => {
console.log("执行effect之前我先清除上一次的结果");
};
}, [toggle]);
// 结果 执行effect之前我先清除上一次的结果-》effect执行
return (
<div>
<button onClick={() => setToggle(!toggle)}>Toggle</button>
</div>
);
Copy const [user, setUser] = useState({});
const id = useLocation().pathname.split("/")[2];
// 请求和清除,
useEffect(() => {
let unsubscribed = false;
fetch(`https://jsonplaceholder.typicode.com/users/${id}`)
.then((res) => res.json())
.then((data) => {
if (!unsubscribed) {
setUser(data);
}
});
return () => {
console.log("cancelled!")
unsubscribed = true;
};
}, [id]);
//FETCH 和 ABORT
useEffect(() => {
const controller = new AbortController();
const signal = controller.signal;
fetch(`https://jsonplaceholder.typicode.com/users/${id}`, { signal })
.then((res) => res.json())
.then((data) => {
setUser(data);
})
.catch((err) => {
if (err === "AbortError") {
console.log("Request canceled!");
}else{
// TODO:handle error
}
});
return () => {
controller.abort();
};
}, [id]);
//Axios和取消请求
useEffect(() => {
const cancelToken = axios.CancelToken.source();
axios
.get(`https://jsonplaceholder.typicode.com/users/${id}`, {
cancelToken: cancelToken.token,
})
.then((res) => {
setUser(res.data);
})
.catch((err) => {
if (axios.isCancel(err)) {
console.log("Request canceled!");
} else {
//TODO:handle error
}
});
return () => {
cancelToken.cancel();
};
}, [id]);
useEffect
vsuseLayoutEffect