Effect
Effect
status: Draft tags: React Created time: November 16, 2022 8:36 PM emoji: https://react.dev/favicon.ico
React组件本质上是一个函数,对于它而言最主要的目的是返回一个基于JSX语法的React组件来构建UI,但是除此之外也需要事件处理程序来处理用户交互。在react组件中有这两种逻辑结构:
rendering code
event handlers
rendering code
指的是描述UI的代码,react系统获取props、state和jsx来构建界面,当props或者state改变时会重新渲染;而event handlers
则是用于处理用户交互的事件处理程序。
但是只有这两种实际上是还不够,有些情况下无法满足我们的需求,例如需要在组件首次渲染时发送http请求获取数据。这个时候无论你将request代码放到rendering code
还是event handles
中都会有问题。
如果你将request放到组件顶层作为rendering code,那么每次组件重新渲染时都会发送一次请求。
如果你将request作为event handles,那么必须要用户进行交互才能发送请求,这显然不合要求。
因此这个时候需要一个新的概念:Effects。E**ffects允许你指定由渲染本身而不是特定事件引起的副作用。**react提供useEffect
这个API来实现函数组件的effect。
useEffect的作用
**useEffect
的作用是实现组件和外部系统的同步**。
在react中,实现外部系统和组件同步的常见方式是利用事件处理程序,在事件处理程序中实现组件和外部系统的同步,但是这种同步需要用户交互实现的,而对于没有用户交互的同步就需要使用useEffect
了。
例如在组件首次渲染时播放音频:
useEffect的三种使用方式
useEffect
接收两个参数,第一个参数是回调函数,第二个函数是依赖数组,只有第一个参数是必须的。第二个参数可以传一个依赖数组,空数组,也可以直接不传,但是这三者之间差距却很大。
这里要注意的是,回调中使用到的状态,必须要在依赖数组中显示表明,系统会检测,如果回调中用到的状态并未在依赖数组中,则会报错。
不传第二个参数 如果不传第二个参数,那么组件每次渲染都会执行回调(包含首次以及每次重新渲染)。
第二个参数传递一个空数组 只有组件首次渲染才会执行回调。
第二个参数传依赖数组 如果传递一个依赖数组,首次渲染时会执行回调,并且每次重新渲染时都会通过
Object.is
来比较依赖数组里的每一项的值与上次渲染时有没有变化,只有当依赖数组每一项都没变化才会跳过执行回调。
我们可以设计一个小程序来验证:
通过点击re-render
按钮来改变state
的值,从而触发重新渲染。由此可以实现组件首次渲染和重新渲染的场景,来观察控制台的值。要注意的是,react在开发环境下会执行Effect回调两次以便帮助开发者发现bug,生产环境下不会有这个问题。
cleanup
前面说过useEffect是在react组件中添加副作用,用于同步组件和外部系统,那么有时候我们需要清除这些副作用,例如在组件销毁时要清除定时器等。
注意事项
useEffect应该只同步外部系统,如果没有外部系统,而您只想根据其他状态调整某些状态,则可能不需要useEffect。
react在开发环境下会执行Effect回调两次依赖debug,生产环境下不会有这个问题。