作为一个react初学者,最近开始尝试使用hooks
在使用useEffect这个api的时候是真的踩了不少坑
踩坑场景一:事件绑定
刚开始我的思路是这样的
1. useEffect 初始化时监听 dom 滚动事件
2. 滚动到底部时 page加1,执行查询方法
于是乎有了一下方法
const getData = () => {
console.log(page);
};
useEffect(() => {
const scrollDom = document.querySelector(".scroll-box");
const func = () => {
setPage((page) => page + 1);
getData();
};
scrollDom.addEventListener("scroll", func);
return () => {
scrollDom.removeEventListener("scroll", func);
};
}, []);
如果按照这样的写法,打印的都是初始值
这个时候你会看到useEffect的依赖里提醒
需要用useCallback包裹一个getData方法
于是我们的代码就变成了
const [page, setPage] = useState(0);
const getData = useCallback(() => {
console.log(page);
},[page]);
useEffect(() => {
const scrollDom = document.querySelector(".scroll-box");
const func = () => {
setPage((page) => page + 1);
getData();
};
scrollDom.addEventListener("scroll", func);
return () => {
scrollDom.removeEventListener("scroll", func);
};
}, [getData]);
这个时候很多同学有像我一样的疑惑
page发生改变的时候,getData也会改变,这个时候会引起 useEffect 再次执行
如此以来,滚动事件不是一直在绑定吗?
我们打印数据验证一下
useEffect(() => {
console.log("注册方法");
const scrollDom = document.querySelector(".scroll-box");
const func = () => {
setPage((page) => page + 1);
getData();
};
scrollDom.addEventListener("scroll", func);
return () => {
console.log("移除方法");
scrollDom.removeEventListener("scroll", func);
};
}, [getData]);
结论:useEffect 在依赖发生改变时会销毁对应的方法,然后重新更新方法里面的变量
踩坑场景二:监听路由参数
我们经常在页面初始化的时候需要获取路由id然后拿到对应的数据
一开始我们的写法是这样的
useEffect(() => {
console.log("请求数据2", getQueryString("id"));
}, []);
这样粗略一看好像没有什么问题
这个时候如果我们改变路由的id参数,发现页面并没有什么变化
这个时候我们在回掉中函数中console发现并没有执行
原因是因为useEffect中的并没有依赖
这个时候需要把 获取参数写到函数外面来
const id = getQueryString("id");
useEffect(() => {
console.log("请求数据", id);
}, [id]);
这样就可以再次渲染了
结论:当我们改变路参数时,那些函数中的声明还是会再次运行,然后useEffect会根据依赖关系来决定是否执行