react - 03.useEffect

43 阅读2分钟

1.默认情况下,useEffect会在组件渲染完成后调用,并且每次渲染完成后调用

useEffect(() => {
    console.log("默认执行Effect")
})

2.useEffect可以传递第二个参数,为数组,数组中可以指定useEffect的依赖项,只有当依赖项发生变化时,useEffect才会被触发

import { useState, useEffect } from 'react'
const App = () => {
  const [count, setCount] = useState<number>(0)
  const handleAdd = () => {
    setCount(count + 1)
  }
  useEffect(() => {
    console.log(count)
  }, [count])
  return (
    <div>
      <div>{count}</div>
      <button onClick={handleAdd}>+</button>
    </div>
  )
}
export default App

当count的值发生变化的时候,才会触发useEffect(useEffect第二个值可以传递多个)

通常实际开发中,useEffect中使用的所有变量都应该设置为依赖项

3.如果依赖项设置了一个空数组,则useEffect只会在组件初始化的时候触发一次(如果希望只触发一次,可以这样写)

import { useState, useEffect } from 'react'
const App = () => {
  const [count, setCount] = useState<number>(0)
  const handleAdd = () => {
    setCount(count + 1)
  }
  useEffect(() => {
    console.log("只执行一次")
    console.log(count) // => 只打印一次渲染之前的值
  }, [])
  return (
    <div>
      <div>{count}</div>
      <button onClick={handleAdd}>+</button>
    </div>
  )
}
export default App

需要注意的是,ueEffect的第二个参数不能为引用类型,因为引用类型比较不出来数据的变化,会造成死循环

import { useState, useEffect } from 'react'
const App = () => {
  const [count, setCount] = useState({
    userName: ""
  })
  const handleAdd = () => {
    setCount({ userName: "AAA" })
  }
  useEffect(() => {
    console.log(count)
    setCount({ userName: "死循环了" })
  }, [count])
  return (
    <div>
      <div>{count.userName}</div>
      <button onClick={handleAdd}>change</button>
    </div>
  )
}
export default App

自己写了一个简单的商品展示搜索demo,还望指正

code.png

3.useEffect清理函数

import { useEffect, useState } from "react"
const App = () => {
  const [searchName, setQueryName] = useState("")
  useEffect(() => {
    console.log("useEffect执行了")
    // 默认先执行清理函数
    // 可以做一些工作来清除上次useEffect执行所带来的影响
    return () => {
      console.log("useEffect的返回函数执行了") // => 在下次执行useEffect函数执行时执行
    }
  }, [searchName])
  return (
    <div></div>
  )
}
export default App

做一个例子,比如我们实现一个表单输入防抖

import { ChangeEvent, useEffect, useState } from "react"
const App = () => {
  const [searchName, setQueryName] = useState<string>("")
  const handleSearch = () => {
    console.log(searchName)
  }
  const handleValue = (e: ChangeEvent<HTMLInputElement>) => {
    setQueryName(e.target.value)
  }
  useEffect(() => {
    const timer = setTimeout(() => {
      setQueryName(searchName) // 4.为searchName设置出发之后的值
      if (searchName) {
        console.log(searchName)
      }
    }, 1000) // 3.又开启了一个新的计时器,当一秒之后没有,值没有变化,执行一次计时器
    return () => {
      clearTimeout(timer) // 2.当触发useEffect函数的时候,默认执行清除函数,并且清除计时器
    }
  }, [searchName]) // 1.当表单中的searchName发生变化的时候,触发useEffect函数
  // 每当值发生变化的时候,不停的清除计时器开启新的计时器,直到值没有变化时,最终执行一次计时器
  return (
    <div>
      <div>
        <input type="search" placeholder='请输入要搜索的商品名称' onChange={handleValue} defaultValue={searchName} />
        <button onClick={handleSearch}>Search</button>
      </div>
    </div>
  )
}
export default App