useEffect() 副作用钩子

useEffect相当于 componentDidMount(组件挂载),componentDidUpdate(组件更新) 和 componentWillUnmount(组件将要销毁) 这三个生命周期函数的组合。

useEffect(() => {
	...
},[])

理解函数副作用

对于React组件来说,主作用是根据数据(state/props)渲染UI,除此之外都是副作用(比如手动修改DOM、发送ajax请求)。
常见的副作用:

函数中有返回值

useEffect 第一个参数函数中有return返回值,即返回值相当于销毁。
相当于原来生命周期的componentWillUnmount(组件销毁前执行)
使用场景

  1. 取消订阅
  2. 清除定时器
  3. 清除window.onresize窗口方法
import React ,{useState,useEffect}from 'react'
function Test() {
  useEffect(() => {
    let timer = setInterval(() => {
      console.log('this is effect');
    }, 1000)
    // 这里return 一个回调函数,在函数中清除副作用
    return () => {
      clearInterval(timer);
    }
  })
  return (
    <div>Test</div>
  )
}
export default function App() {
  const [flag, setFlag] = useState(true);
  return (
    <div>
      {flag ? <Test/> : null}
      <div>
        <button onClick={() => setFlag(!flag)}>点击</button>
      </div>
    </div>
  )
}

点击按钮,Test组件卸载,清除定时器timer

默认状态(无依赖项)

useEffect 不传递第二个参数,表示不监听任何参数的变化。
每次渲染DOM之后,都会执行 useEffect 中的第一个函数。

import React from 'react'
export default function App() {
	const [count, setCount] = useState(0);
	useEffect(() => {
		console.log("触发副作用");
	});
	return (
		<div>
		  <p>点击{count}</p>
			<button onClick={() => setCount(count + 1)}>Click</button>
		</div>
	)
}

依赖项为空数组

useEffect 函数还可以接收第二个参数,作为该副作用的依赖项,当第二个参数 传入一个空数组[] 时,表明只有 组件初始化的时候执行一次
相当于componentDidMount(组件挂载)

import React from 'react'
export default function App() {
	const [count, setCount] = useState(0);
	useEffect(() => {
		console.log("触发副作用");
		document.title = `点击了${count}`;
	}, []); // 注意这里,传入 []
	return (
		<div>
		  <p>点击{count}</p>
			<button onClick={() => setCount(count + 1)}>Click</button>
		</div>
	)
}

依赖特定项

依赖项数组中传入值时,那么该副作用会在 组件初始化的时候执行一次,依赖的特定项变化时会再次执行
就像componentDidMountcomponentDidUpdate组合的生命周期函数一样

function App() {
  const [count, setCount] = useState(0);
  const [name, setName] = useState('李白');
  useEffect(() => {
    console.log('触发渲染')
    document.title = `clicked ${count} times`;
    console.log('name: ', {name});
  },[count]) // 这里我们传入 count,不传name
  return (
    <>
      <p>当前次数:{count}</p>
      <p><button onClick={() => setCount(count + 1)}>累计</button></p>
      <p><button onClick={() => setName("杜甫")}>改名{name}</button></p>
    </>
  )
}

发送网络请求

不可以直接在 useEffect 的回调函数外层直接包裹await,因为异步会导致清理函数无法立即返回
❌错误示例:

useEffect(async () => {
    const res = await getData('url');
    console.log(res);
})

可在 useEffect 中定义一个请求数据方法,调用。

正确示例:

useEffect(() => {
    async function initData() {
        const res = await getData('url');
        console.log(res);
    }
    initData()
}, []) // 仅组件初始化时调用

发表回复