react hook -- useEffect

使用Effect hook可以在函数组件中执行副作用

副作用 - 指一段和当前执行结果无关的代码。

  • data fetching
  • setting up a subscription
  • manually changing the DOM
  • logging

useEffect 可以看作是 componentDidMount, componentDidUpdatecomponentWillUnmount 的结合,且useEffect不会阻塞浏览器更新screen。

useEffect 使用方法及执行时机:

  1. Effects Without Cleanup - 该例子会在每次render之后都执行effect
    • 组建挂载后-componentDidMount
    • 每次update后-componentDidUpdate
useEffect(() => {
  document.title = `You clicked ${count} times`;
})
  1. Effects With Cleanup - 该例子的effect返回了一个函数
    • 其他内容在每次render之后会执行
    • 返回的函数内容会在组件卸载之前(等同于componentWillUnmount)执行
useEffect(() => {
  const handStatusUpdated = (status) => {
    setIsOnline(status.isOnline)
  }
  ChatAPI.subscribe(friend.id, handStatusUpdated);
  return ChatAPI.unsubscribe(friend.id, handStatusUpdated);
})
  1. 在同一个组件中多次使用useEffect - React会按照指定的顺序应用每个effect
  2. Skipping Effects - 只有count改变才会re-runeffect
useEffect(() => {
  document.title = `You clicked ${count} times`;
}, [count])
useEffect(() => {
  const handStatusUpdated = (status) => {
    setIsOnline(status.isOnline)
  }
  ChatAPI.subscribe(friend.id, handStatusUpdated);
  return ChatAPI.unsubscribe(friend.id, handStatusUpdated);
}, [friend.id])
  1. 只在mountunmount时运行的effect - 依赖项传入空数组并返回函数
useEffect(() => {
  // code block mount时执行
  return () => {
    // code block unmount时执行
  }
}, [])

Hooks 的依赖项

Hooks 提供了让你监听某个数据变化的能力。这个变化可能会触发组件的刷新,也可能是去创建一个副作用,又或者是刷新一个缓存。那么定义要监听哪些数据变化的机制,其实就是指定 Hooks 的依赖项。

定义依赖项时,需要注意以下三点:

  • 依赖项中定义的变量一定是会在回调函数中用到的,否则声明依赖项其实是没有意义的。
  • 依赖项一般是一个常量数组,而不是一个变量。因为一般在创建 callback 的时候,你其实非常清楚其中要用到哪些依赖项了。
  • React 会使用浅比较对比依赖项是否发生了变化,所以要特别注意数组或者对象类型。
function Sample() {
  // 这里在每次组件执行时创建了一个新数组
  const todos = [{ text: 'Learn hooks.'}];
  useEffect(() => {
    console.log('Todos changed.');
  }, [todos]);
}

代码的原意可能是在 todos 变化的时候去产生一些副作用,但是这里的 todos 变量是在函数内创建的,实际上每次都产生了一个新数组。

useEffect 与三种生命周期方法


useEffect(() => {
  // componentDidMount + componentDidUpdate
  console.log('这里基本等价于 componentDidMount + componentDidUpdate');
  return () => {
    // componentWillUnmount
    console.log('这里基本等价于 componentWillUnmount');
  }
}, [deps])

基本等价于的含义:

  • 一方面,useEffect(callback) 这个 Hook 接收的 callback,只有在依赖项变化时才被执行。而传统的 componentDidUpdate 则一定会执行。在componentDidUpdate 中,我们通常都需要手动判断某个状态是否发生变化,然后再执行特定的逻辑。
  • 另一方面,callback 返回的函数(一般用于清理工作)在下一次依赖项发生变化以及组件销毁之前执行,而传统的 componentWillUnmount 只在组件销毁时才会执行。

useEffect 接收的返回值是一个回调函数,这个回调函数不只是会在组件销毁时执行,而且是每次 Effect 重新执行之前都会执行,用于清理上一次 Effect 的执行结果。

总结

学习useEffect要理解什么是副作用以及使用useEffect传入不同的参数时能达到什么效果。虽然 Hooks 在功能上基本可以映射到传统的 Class 组件的生命周期方法,但是它们却又不是完全等价的。在实现具体的业务功能的时候,都应该尽量从 Hooks 的语义角度出发去思考组件是如何展现和交互的,这样才能更加顺滑地切换到函数组件的开发方式。

在函数组件中你要思考的方式永远是:当某个状态发生变化时,我要做什么,而不再是在 Class 组件中的某个生命周期方法中我要做什么。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容