学习笔记——useEffect()首次加载不调用

5,823 阅读2分钟

背景:公司新开一个项目,因为从前项目用到的技术很平庸,所以想尝试一下使用hooks来写项目。但由于个人水平比较菜,中间踩过一些坑,所以开了一个学习笔记作为自己的学习总结,希望能不断提升自己。学习笔记包括但不限于工作中用到的hooks。

场景:项目是一个后台管理系统,会有一些含有表格的页面。由于首次加载页面和点击分页时都需要发送一次请求来获取表格数据,而两者是相互独立的,所以就写了两个useEffect钩子来分别处理,这就导致了页面首次加载的时候会请求两次数据,因此有了‘useEffect()首次加载不调用’这个需求。

在类组件中这样的场景很好处理,可以把分页后的请求写在改变页码后的setState回调里

在react的函数组件中,我们可以通过useEffect()这个钩子来替代componentDidMount()这个生命周期函数,但是似乎每次页面渲染的时候都会调用,而当业务需求需要我们创建两个或多个useEffect(),且需要部分不在页面首次渲染被调用时,该如何处理。这对刚开始接触学习使用hooks的我来说造成了一些困扰。

最开始的思路是定义一个变量来存储页面是否首次加载这个状态,然后根据这个状态来进行相关操作。但是觉得hooks肯定有更方便的方法。

通过查询相关文档,我得知我们可以通过useRef()来记录(或者是跟踪?)页面是否首次渲染,从而来判断是否需要调用相关的useEffect()

之前的代码

项目使用了antd组件库

const [params, setParams] = useState({
    page_size: 6,
    total: 150,
    page: 1,
})

const handleChangePage = (page, pageSize) => {      // 分页器发生变化
    console.log('before_page', params.page)
    setParams({
        ...params,
        page,
    })
}
useEffect(() => {
    console.log('after_page', params.page)
}, [params.page])

使用useRef()之后的代码

const firstUpload = useRef(true)        // 记录是否是首次加载页面
useEffect(() => {      
    if (firstUpload.current) {
        firstUpload.current = false
        return
    }
    console.log('after_page', params.page)
}, [params.page])

我查到有人用useLayoutEffect()来代替useEffect(),于是我又去查了下二者的区别。

useLayoutEffect里面的callback函数会在DOM更新完成后立即执行

也就是说如果我们希望效果在componentDidUpdate中运行,我们可以使用useLayoutEffect