[React] useEffect

发布时间 2023-05-21 20:24:35作者: Akira300000

pure function:单纯返回jsx元素的组件

在使用react函数组件时,理论上函数组件只会进行不改变内部状态值的计算,以及返回html代码。一个pure函数就是如此,例如一个函数组件接受一个id作为传入属性,注意这里传入的id并没有发生变化,我们只是简单进行了输出和数学计算:

// this is a pure function!
export default function person({ id }) {
  return (
    <>
    <p>Nice to meet you! #{id}</p>
	<p>Change your id to #{id*3}</p>
	</>
  )
}

impure function:不仅仅只是返回jsx元素

然而实际运用中,一个组件绝不止单纯返回jsx代码,在最后返回渲染代码之前可能还需要更多操作,例如修改DOM,获取数据,修改表单输入,提交表单甚至是重定向一个新页面。react doc将这些情况归纳为事件处理器(event handler)。因为组件内部的状态值被修改了,因此会发生副作用(side effects),这时候useEffect就发挥作用了。

// this is not a pure function!
export default function person({ id }) {
  let cnt = 0;
  return (
    <>
    <p>Nice to meet you! #{id}</p>
	<p>Change your id to #{id*3}</p>
	<p>Let's change the count number: {cnt++}</p>
	</>
  )
}

useEffect在执行什么:一个函数

useEffect本身就是一个函数,它的第一个参数也是函数,而且这个函数会改变组建的状态,所以我们将这个函数放入useEffect中

useEffect(() => {
  if (welcome) {
    document.querySelector("p").innerHTML = 'welcome, user!';
  }
})

这个函数改变了p标签下的文本,也就是修改了DOM,属于副作用的范围。

注意:使用useEffect的情况应该是组件中被用于渲染的状态发生了改变,而组件中有些状态值是不参与渲染的,这个时候就不需要使用useEffect了。

useEffect的第二个参数:什么时候运行这个函数?

第二个参数就是一个包含了所有依赖项的列表,说明当这个列表中的任意对象的状态发生改变时,useEffect就会激活。

// 依赖不为空:当welcome发生改变时,输出不同的文本
useEffect(() => {
  if (welcome) {
    document.querySelector("p").innerHTML = 'welcome, user!';
  }
  else {
    document.querySelector("p").innerHTML = 'Hola! como easta?';
  }
}, [welcome])

依赖可以为空或没有

// 依赖为空:只在组件第一次渲染时运行,重新渲染就不会再跑一次了
useEffect(() => {
  conn = getConnection()
  setMessages(conn.getMessages(id))
}, [])
// 没有依赖:无上限地渲染,不建议因为不停重复渲染会导致性能下降,很多时候也没必要
useEffect(() => {
  conn = getConnection()
  setMessages(conn.getMessages(id))
})

useEffect运行的时机:在网页更新之后

根据react docs,useEffect会在建立网页的最后一步commit中触发,准确来说是在DOM被渲染/更新之后,然后由useEffect中的函数来更新部分有变化的DOM。

但是在某些情况下,有些状态值不会导致DOM变化,且函数也没有直接修改DOM的代码,因此即便使用useEffect也没用,数据不会被更新甚至渲染,这时候就要使用useMemo在渲染/更新之前来控制这些状态。

总结

  • 大部分组件会有修改DOM和jsx元素的代码,因此不是pure function
  • useEffect是针对那些有副作用的组件,并通过依赖来控制触发的条件
  • useEffect运行的时候网页已经渲染完毕了,要注意其在react渲染全过程中的时间点