React hooks 可以實現 class 組件的很多功能,平時開發中我們也會經常遇到在組件渲染不同階段執行一些業務邏輯。這類需求在 class 組件中是非常容易實現的,那么使用 hooks 是否也能實現呢,答案當然是肯定的。
下面,我們就來用 hooks 模擬 class 組件的生命周期:
class 組件 | hooks 組件 |
---|---|
constructor | useState |
getDerivedStateFromProps | 更新 useState 里面的 update 函數 |
shouldComponentUpdate | React.memo |
render | 函數本身 |
componentDidMount | useEffect |
componentDidUpdate | useEffect |
componentWillUnmount | useEffect 里面返回的函數 |
componentDidCatch | 無 |
getDerivedStateFromError | 無 |
關於useEffect中的參數問題:
useEffect 擁有兩個參數,第一個參數作為回調函數會在瀏覽器布局和繪制完成后調用,因此它不會阻礙瀏覽器的渲染進程;第二個參數是一個數組。
下面是第二個參數的說明:
- 當數組存在並有值時,如果數組中的任何值發生更改,則每次渲染后都會觸發回調;
- 當它不存在時,每次渲染后都會觸發回調;
- 當它是一個空列表時,回調只會被觸發一次,類似於 componentDidMount;
下面通過代碼來做下具體的演示:
constructor
class 組件
class Example extends Component { constructor() { super(); this.state = { num: 0 } } render() { return <div>{ this.state.num }</div>; } }
函數組件不需要構造函數,可以通過調用 useState 來初始化 state
function Example() { const [num, setNum] = useState(0); return <div>{ num }</div>; }
componentDidMount
class 組件中使用 componentDidMount
class Example extends React.Component { componentDidMount() { console.log('componentDidMount!'); } render() { return null; } }
使用 hooks 模擬 componentDidMount
function Example() { useEffect(() => console.log('componentDidMount'), []); return null; }
shouldComponentUpdate
class 組件中使用 shouldComponentUpdate
shouldComponentUpdate(nextProps, nextState){ console.log('shouldComponentUpdate') // return true 更新組件 // return false 則不更新組件 }
使用 hooks 模擬 shouldComponentUpdate
const MemoComponent = React.memo( HeaderComponent, (prevProps, nextProps) => nextProps.count !== prevProps.count )
componentDidUpdate
class 組件中使用 componentDidUpdate
componentDidUpdate() { console.log('mounted or updated'); }
使用 hooks 模擬 componentDidUpdate
useEffect(() => console.log('mounted or updated'));
回調函數會在每次渲染后調用,因此不僅可以訪問 componentDidUpdate,還可以訪問componentDidMount,如果只想模擬 componentDidUpdate,我們可以這樣來實現
const mounted = useRef(); useEffect(() => { if (!mounted.current) { mounted.current = true; } else { console.log('didUpdate') } });
useRef 在組件中創建“實例變量”。它作為一個標志來指示組件是否處於掛載或更新階段。當組件更新完成后在會執行 else 里面的內容,以此來單獨模擬 componentDidUpdate。
componentWillUnmount
class 組件中使用 componentWillUnmount
componentWillUnmount() { console.log('componentWillUnmount'); }
使用 hooks 模擬 componentWillUnmount
useEffect(() => { return () => { console.log('willUnmount'); } }, []);