【React Hooks 学习笔记】useEffect

简介: 前端西瓜哥

大家好,我是前端西瓜哥。

今天继续讲 React Hooks 中 useEffect 的用法。

useEffect 用于实现副作用,在这里你将会脱离声明式,写命令式的代码。准确来说,写的是与通过声明式控制 DOM 数无关的代码。

执行的时机是在组件完成渲染之后,进行下一轮渲染之前。

如果你熟悉类组件,你可以将 useEffect 当作是 componentDidMount(组件挂载)、componentDidUpdate(组件更新) 和 componentWillUnmount(组件销毁) 这三个生命周期函数的组合体。

每次渲染后都执行

useEffect 默认情况(不提供第二个参数)下会在每次的组件被重新渲染后,执行传入的回调方法。

useEffect(() => {
 console.log('组件被渲染');
});

这种写法,无论在组件初次挂载时,还是之后的更新都会被触发,这和类组件的 componentDidUpdate 有点区别。

如果你想实现 componentDidUpdate 的效果,你得写个自定义 hook 或使用一些开源方案,比如 ahooks 的 useUpdateEffect。

只在第一次渲染时执行

useEffect 除了支持每次渲染都执行,还可以做更细粒度的控制:只在第一次渲染时,也就是组件挂载的时候执行一次回调函数。

写法为:

useEffect(() => {
 console.log('组件被挂载');
},[]);

可以看到,我们这里提供了第二个参数,一个依赖项数组。

React 会比较将要执行的渲染和上次渲染的每个对应的依赖项是否不同。如果全都相同,就不会执行回调函数;如果有一个不同,则会执行。不过第一次渲染时,并没有上次渲染,所以一定会被执行。

传一个空数组,其实意思就是:我的依赖项永远不会变,你执行完第一次就不要再执行了。

因此可以实现类组件中 componentDidMount 的效果。

依赖项设置为空数组是比较特殊的用法,专用于挂载事件。其实更常见的写法如下:

useEffect(() => {
  document.title = '当前计数值:' + count;
}, [count]);

我们希望在 count 发生改变时,才执行回调函数。如果你还懂 Vue,其实这就像是 watch() 监听函数一样,监听着 count 这个变量的变化,非常好用的机制属于是。

但依赖项数组有局限性:只会做是否相同的比较,且多个依赖项是逻辑或的关系。如果你的比较逻辑比较复杂,还得自己写一个判断条件。

组件销毁时执行

当我们希望组件销毁时,执行一个函数,又该如何写呢?

这个 useEffect 也支持,useEffect 会将传入的回调函数执行后的返回的函数保存起来,在组件销毁时或进行下一次渲染前执行。

useEffect(() => {
  return () => {
    console.log('组件销毁');
  }
}, []);

这个函数是否会执行,也和依赖项数组有关。

如果依赖项没有变化,组件重新渲染也不会执行它。但如果是整个组件被销毁了,这个函数一定会被执行。

这里的 return 是不能随便返回的。在函数中我习惯在 if 条件中通过 return 来结束分支,来减少 if 的嵌套,但这在 useEffect 里就要慎用了,可能一不小心以为提前返回,将 undefined 取代了一个本该返回的销毁函数。

useEffect 之所以会用回调函数返回的函数这种看似奇怪的写法,是为了通过闭包,让返回的函数能够拿到需要的变量,常见的用途有事件响应函数的绑定和取消,如:

useEffect(() => {
  const handler = () => {
    console.log('鼠标按下');
  }
  window.addEventListener('mousedown', handler);
  return () => {
    window.removeEventListener('mousedown', handler);
  }
}, []);

返回的函数需要 handler 来取消事件绑定,闭包的方式才能让它拿到。

结尾

useEffect 很有魔性,只要一个 API,它就能实现:

  • 组件挂载钩子
  • 组件更新钩子
  • 组件销毁钩子
  • 监听状态值的变化

看起来像是违背了单一职责原则,但其实你可以把 useEffect 当作比普通组件粒度更小的一个 “小组件”,一个新的小世界,这为我们做更小粒度的功能解耦提供了新的解决方案,但却不失优雅。

相关文章
|
2月前
|
前端开发 JavaScript
React Hooks 全面解析
【10月更文挑战第11天】React Hooks 是 React 16.8 引入的新特性,允许在函数组件中使用状态和其他 React 特性,简化了状态管理和生命周期管理。本文从基础概念入手,详细介绍了 `useState` 和 `useEffect` 的用法,探讨了常见问题和易错点,并提供了代码示例。通过学习本文,你将更好地理解和使用 Hooks,提升开发效率。
70 4
|
2月前
|
前端开发
深入解析React Hooks:构建高效且可维护的前端应用
本文将带你走进React Hooks的世界,探索这一革新特性如何改变我们构建React组件的方式。通过分析Hooks的核心概念、使用方法和最佳实践,文章旨在帮助你充分利用Hooks来提高开发效率,编写更简洁、更可维护的前端代码。我们将通过实际代码示例,深入了解useState、useEffect等常用Hooks的内部工作原理,并探讨如何自定义Hooks以复用逻辑。
|
20天前
|
前端开发 JavaScript
深入探索React Hooks:从useState到useEffect
深入探索React Hooks:从useState到useEffect
|
1月前
|
前端开发 JavaScript 开发者
“揭秘React Hooks的神秘面纱:如何掌握这些改变游戏规则的超能力以打造无敌前端应用”
【10月更文挑战第25天】React Hooks 自 2018 年推出以来,已成为 React 功能组件的重要组成部分。本文全面解析了 React Hooks 的核心概念,包括 `useState` 和 `useEffect` 的使用方法,并提供了最佳实践,如避免过度使用 Hooks、保持 Hooks 调用顺序一致、使用 `useReducer` 管理复杂状态逻辑、自定义 Hooks 封装复用逻辑等,帮助开发者更高效地使用 Hooks,构建健壮且易于维护的 React 应用。
32 2
|
2月前
|
前端开发 开发者
React 提供的其他重要 Hooks
【10月更文挑战第20天】React 提供了一系列强大的 Hooks,除了 `useRef` 之外,还有许多其他重要的 Hooks,它们共同构成了函数式组件开发的基础。
35 6
|
12天前
|
缓存 前端开发 开发者
深入理解React Hooks,打造高效响应式UI
深入理解React Hooks,打造高效响应式UI
22 0
|
2月前
|
前端开发 JavaScript 开发者
React Hooks
10月更文挑战第13天
36 1
|
2月前
|
前端开发
|
2月前
|
前端开发 JavaScript API
自定义React Hooks综合指南
本文介绍了React Hooks及其在组件开发中的作用,重点讲解了自定义Hook的创建和使用方法。通过实例展示了如何创建`useWindowWidth`、`useFetch`和`useForm`等自定义Hook,并分享了使用自定义Hook的最佳实践。文章强调了自定义Hook在提高代码复用性和组件可维护性方面的重要性。
62 0
|
2月前
|
存储 前端开发 JavaScript
深入理解React组件的生命周期与Hooks
【10月更文挑战第7天】深入理解React组件的生命周期与Hooks
104 0