React Hooks -- useEffect

91 阅读1分钟

一、获取接口数据

useEffect会在hook组件渲染(包含第一次和后续每次渲染)的时候重新执行。

useEffect接受两个参数,第一个参数是一个函数,第二参数是一个数组。

若第二个参数为空数组,则表示useEffect只在第一次渲染后执行,后续不再重新执行。此逻辑适合页面第一次渲染加载接口数据的业务场景。

import React, { useState, useEffect } from 'react'

function Example1(){
  const [loading, setLoading] = useState(true)
  const [data, setData] = useState({})
  useEffect(() => {
      const fetchData = async () => {
         try {
            const res = await getInterfaceName(params)
            setData(res)
          } catch (error) {
            throw error
          } finally {
            setLoading(false)
          }
      }
      fetchData()
  }, [])
  return (
    <div>
      {loading ? loading...' : <>{data}</>}
    </div>
  )
}

export default Example1

二、控制执行时机

依赖项中数据发生变化时候,useEffect会重新执行。实际业务场景中可以根据依赖项实现复杂的业务需求。

import React, { useState, useEffect } from 'react'

function Example2(props){
  const { parentState } = props
  const [count, setCount] = useState(0)
  const [number, setNumber] = useState(0)
  useEffect(() => {
      const handleNumber = () => {
          setNumber(count + 1)
      }
      handleNumber()
      // 点击count事件增加时,因为count发生变化,所以handleNumber函数会重新执行
      // 另数组依赖项也可以是父组件传递过来的,当父组件中parentState发生变化,子组件中的handleNumber也会重新执行
  }, [parentState, count])
  
  return (
    <div>
      <p onClick={prevState => setCount(prevState + 1)}>
        Count: {count}
      </p>
      <br />
      <p>Number: {number}</p>
    </div>
  )
}

export default Example2

三、绑定/卸载事件

第一个函数的返回值可以是另一个函数,用于在组件卸载时执行移除监听的事件

import React, { useState, useEffect, useRef } from 'react'

function Example3(){
  const [muted, setMuted] = useState(false)
  const videoEl = useRef(null)
  
  useEffect(() => {
    const videoElement = videoEl.current
    videoElement.addEventListener('timeupdate', handleTimeDate, false)
    videoElement.addEventListener('loadedmetadata', handleLoadedMetaData, false)
    videoElement.addEventListener('durationchange', handleDurationChange, false)
    videoElement.addEventListener('play', handlePlay, false)
    videoElement.addEventListener('error', handleVideoError, false)
    videoElement.addEventListener('waiting', handleVideoWaiting, false)
    videoElement.addEventListener('playing', handleVideoPlaying, false)
    videoElement.addEventListener('ended', addPlayTimeEvent, false)
    return () => {
      videoElement.removeEventListener('timeupdate', handleTimeDate)
      videoElement.removeEventListener('loadedmetadata', handleLoadedMetaData)
      videoElement.removeEventListener('durationchange', handleDurationChange)
      videoElement.removeEventListener('play', handlePlay)
      videoElement.removeEventListener('error', handleVideoError)
      videoElement.removeEventListener('waiting', handleVideoWaiting)
      videoElement.removeEventListener('playing', handleVideoPlaying)
      videoElement.removeEventListener('ended', addPlayTimeEvent)
    }
  }, [])
  
  return (
    <div>
      <video
       ref={videoEl}
       muted={muted}
       src={videoSrc}
       autoPlay={true}
      >
      </video>
    </div>
  )
}

export default Example3