/*useEffect用于在“渲染之后”执行副作用逻辑
useEffect(()=>{
回调函数:数据请求、手动操作dom、添加监听事件、定时器
return ()=>{
断开数据请求、移除监听器、结束定时器
}
},[])
useEffect用于异步获取数据(服务接口),不影响后续代码的渲染,回调函数执行完后对结果进行更新渲染
无依赖项:每一次组件渲染完成之后都会执行
[]:只在组件首次渲染之后执行
[a, b]:组件渲染完成,并且a或b发生变化时才执行
useEffect回调函数的返回值(清理函数),可以没有,有就必须是一个函数,它的执行时机:
1.组件被销毁时
2.第二次执行useEffect时,会优先调用第一次执行时的return函数里面的内容,然后再去执行useEffect里面的代码
*/
import { useEffect, useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `当前计数:${count}`;
}, [count]); // 依赖数组:只在 count 改变后运行
return (
<div>
<p>计数:{count}</p>
<button onClick={() => setCount((c) => c + 1)}>+1</button>
<button onClick={() => setCount(0)}>重置</button>
</div>
);
}
export function FetchData() {
const [users,setUsers] = useState([])
const [error,setError] = useState(null)
const [tick, setTick] = useState(0)
const [size,setSize] = useState({w:window.innerWidth,h:window.innerHeight})
//首次挂载时拉取数据
useEffect(()=>{
const controller = new AbortController();
//数据请求
async function load() {
try {
const res = await fetch("https://XXXX/users", {
signal: controller.signal,
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
setUsers(data);
} catch (e) {
setError(e);
}
}
load();
//事件监听
function onResize() {
setSize({w:window.innerWidth,h:window.innerHeight})
}
window.addEventListener("resize",onResize)
//定时器
const id= setInterval(()=> setTick((t)=>t+1), 1000)
return () => {
controller.abort();// 清理:依赖变更或卸载时取消未完成请求
window.removeEventListener('resize',onResize)//清理事件监听
clearInterval(id)//清理定时器
}
},[])
//上面load函数如果不用await,如何写?这样看来用await写会更直观
function load1() {
fetch("/api").then((res)=>{
if(!res.ok) throw new Error(`HTTP ${res.status}`)
return res.json() //返回一个Promise
}).then((data)=>{
setUsers(data) //解析完成后拿到data
}).catch((e)=>{
setError(e)
})
}
return (
<div>
<ul>
{
users.map(user=>(
<li key={user.id}>{user.name}</li>
))
}
</ul>
<div>窗口:{size.w} * {size.h}</div>
<div>Tick:{tick}</div>
</div>
)
}
console