useEffect常见踩坑记录

1,246 阅读2分钟

作为一个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]);

image.png

结论:useEffect 在依赖发生改变时会销毁对应的方法,然后重新更新方法里面的变量

踩坑场景二:监听路由参数

我们经常在页面初始化的时候需要获取路由id然后拿到对应的数据

一开始我们的写法是这样的

  useEffect(() => {
    console.log("请求数据2", getQueryString("id"));
  }, []);

这样粗略一看好像没有什么问题
这个时候如果我们改变路由的id参数,发现页面并没有什么变化

这个时候我们在回掉中函数中console发现并没有执行
原因是因为useEffect中的并没有依赖

这个时候需要把 获取参数写到函数外面来

const id = getQueryString("id");
useEffect(() => {
  console.log("请求数据", id);
}, [id]);

这样就可以再次渲染了

结论:当我们改变路参数时,那些函数中的声明还是会再次运行,然后useEffect会根据依赖关系来决定是否执行