React useEffect


今早來又莫名其妙的遇到了 bug,排查了一下是 useEffect 導致的。今天就再來詳細的學習一下 react useEffect。

為什么要?

我們知道,react 的函數組件里面沒有生命周期的,也沒有 state,沒有 state 可以用 useState 來替代,那么生命周期呢?

useEffect 是 react v16.8 新引入的特性。我們可以把 useEffect hook 看作是componentDidMount、componentDidUpdate、componentWillUnmounrt三個函數的組合。

詳解

原來我們是這么寫 class component

class LifeCycle extends React.Component {
	constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }
  componentDidMount() {
    document.title = `you clicked me ${this.state.count} times`;
  }
  componentDidUpdate() {
    document.title = `you clicked me ${this.state.count} times`
  }
  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={()=> this.setState({count: this.state.count + 1})}>
        	Click me
        </button>
      </div>
    )
  }
}

現在我們使用 hook 來寫 function component

import React, { useState, useEffect } from 'react';
function Example() {
	const [count, setCount] = useState(0);
	useEffect(() => {
		document.title = `you clicked ${count} times`;
	})
	return (
		<div>
			<p>You clicked {count} times</p>
			<button onClick={() => setCount(count + 1)}
				Click me
			</button>
		</div>
	)
}

上面的這段代碼,每次 count 變更以后,effect都會重新執行。

我們日常開發中,獲取數據、訂閱以及手工更改 React 組件中的 DOM(我之前就更改過)都屬於副作用。有些副作用可能需要清除,所以需要返回一個函數,比如設置定時器、清除定時器。

class Example extends Component {
	constructor(props) {
		super(props);
		this.state = {
			count: 0;
		}
	}
	componentDidMount() {
		this.id = setInterval(() => {
			this.setState({count: this.state.count + 1})
		}, 1000)
	}
	componentWillUnmount() {
		clearInterval(this.id)
	}
	render() {
		return <h1>{this.state.count}</h1>;
	}
}

使用 Hook 的示例

function Example() {
	const [count, setCount] = useState(0);
	useEffect(() => {
		const id = setInterval(() => {
			setCount(c => c + 1);
		}, 1000);
		return () => clearInterval(id);
	}, []);
	return <h1>{count}</h1>
}

我們可以讓 React 跳過對 effect 的調用,讓 effect 的執行依賴於某個參數(傳利數組作為 useEffect 的第二個可選參數就可以了)。倘若僅僅只想執行一次,那么就傳遞一個空的數組作為第二個參數,這個時候 useEffect hook 不依賴於 props 或者任何值,所以永遠都不重復執行。

在過去的性能優化里,在某些情況下,每次渲染后都執行清理或者執行 effect 都可能會導致性能的問題。在 class 組件中,我們通過在 componentDidUpdate 添加 prevProps或者 prevState 來解決。

componentDidUpdate(prevProps, prevState) {
	if(prevState.count !== this.state.count) {
		document.title = `You clicked ${this.state.count} times`
	}
}

這個是非常常見的需求。而如今,倘若我們使用 function component,代碼會非常的簡潔。

useEffect(() => {
	document.title = `You clicked ${count} times`;
}, [count])

總結

Hook 是對函數式組件的一次增強,v16.8 出現以后才出來的 hook 特性。在這之前,我看有的代碼里面,通過一個<InitialCallBack>來放到函數時組件的最前面,通過在<InitialCallBack>的 componentDidMount 來獲取后端接口數據。

就是變相的往 Hook 里面引入生命周期。

然而 v16.8 出來了,這個問題完全解決了。

Hook的語法更簡潔易懂,消除了 class 的聲明周期方法導致的重復邏輯代碼。

同時,在某種程度上解決了高階組件難以理解和使用的問題。

然而 Hook 並沒有讓函數時組件做到 class 組件做不到的事情,只是讓很多組件變得寫的更簡單。class 組件不會消失,hook 化的函數時組件將是趨勢。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM