React中useEffect使用


640?wx_fmt=png

之前我們已經掌握了useState的使用,在 class 中,我們通過在構造函數中設置 this.state 為 { count: 0 } 來初始化 count state 為 0

 

 

  1.  
    class Example extends React.Component {
  2.  
    constructor(props) {
  3.  
    super(props);
  4.  
    this.state = {
  5.  
    count: 0
  6.  
    };
  7.  
    }

 

在函數組件中,我們沒有 this,所以我們不能分配或讀取 this.state。我們直接在組件中調用 useState Hook:

 

 

  1.  
    import React, { useState } from 'react';
  2.  
     
  3.  
     
  4.  
    function Example() {
  5.  
    // 聲明一個叫 “count” 的 state 變量
  6.  
    const [count, setCount] = useState(0);

 

既然我們知道了 useState 的作用,那么掌握 useEffect 就更容易,函數組件中沒有生命周期,那么可以使用 useEffect 來替代。如果你熟悉 React class 的生命周期函數,你可以把 useEffect Hook 看做 componentDidMountcomponentDidUpdate 和 componentWillUnmount 這三個函數的組合。

 

 

  1.  
    class Example extends React.Component {
  2.  
    constructor(props) {
  3.  
    super(props);
  4.  
    this.state = {
  5.  
    count: 0
  6.  
    };
  7.  
    }
  8.  
    componentDidMount() {
  9.  
    document.title = `You clicked ${this.state.count} times`;
  10.  
    }
  11.  
    componentDidUpdate() {
  12.  
    document.title = `You clicked ${this.state.count} times`;
  13.  
    }
  14.  
    render() {
  15.  
    return (
  16.  
    <div>
  17.  
    <p>You clicked { this.state.count} times</p>
  18.  
    <button onClick={() => this.setState({ count: this.state.count + 1 })}>
  19.  
    Click me
  20.  
    </button>
  21.  
    < /div>
  22.  
    );
  23.  
    }
  24.  
    }

 

使用 Hook 的示例

 

  1.  
    import React, { useState, useEffect } from 'react';
  2.  
     
  3.  
     
  4.  
    function Example() {
  5.  
    const [count, setCount] = useState(0);
  6.  
     
  7.  
     
  8.  
    useEffect(() => {
  9.  
    document.title = `You clicked ${count} times`;
  10.  
    });
  11.  
     
  12.  
     
  13.  
    return (
  14.  
    <div>
  15.  
    <p>You clicked {count} times< /p>
  16.  
    <button onClick={() => setCount(count + 1)}>
  17.  
    Click me
  18.  
    </button>
  19.  
    < /div>
  20.  
    );
  21.  
    }

 

默認情況下,它在第一次渲染之后和每次更新之后都會執行。你可能會更容易接受 effect 發生在“渲染之后”這種概念,不用再去考慮“掛載”還是“更新”。React 保證了每次運行 effect 的同時,DOM 都已經更新完畢。

 

數據獲取,設置訂閱以及手動更改 React 組件中的 DOM 都屬於副作用。有些副作用可能需要清除,所以需要返回一個函數,比如掛載時設置定時器,卸載時取消定時器。

 

 

  1.  
    class Example extends Component {
  2.  
    constructor (props) {
  3.  
    super(props);
  4.  
    this.state = {
  5.  
    count: 0
  6.  
    }
  7.  
    }
  8.  
    componentDidMount() {
  9.  
    this.id = setInterval(() => {
  10.  
    this.setState({count: this.state.count + 1})
  11.  
    }, 1000);
  12.  
    }
  13.  
    componentWillUnmount() {
  14.  
    clearInterval( this.id)
  15.  
    }
  16.  
    render() {
  17.  
    return <h1>{this.state.count}</h1>;
  18.  
    }
  19.  
    }

 

使用 Hook 的示例

 

  1.  
    function Example() {
  2.  
    const [count, setCount] = useState(0);
  3.  
     
  4.  
     
  5.  
    useEffect(() => {
  6.  
    const id = setInterval(() => {
  7.  
    setCount(c => c + 1);
  8.  
    }, 1000);
  9.  
    return () => clearInterval(id);
  10.  
    }, []);
  11.  
     
  12.  
     
  13.  
    return <h1>{count}</h1>
  14.  
    }

 

你可以通知 React 跳過對 effect 的調用,只要傳遞數組作為 useEffect 的第二個可選參數即可,如果想執行只運行一次的 effect(僅在組件掛載和卸載時執行),可以傳遞一個空數組([])作為第二個參數。這就告訴 React 你的 effect 不依賴於 props 或 state 中的任何值,所以它永遠都不需要重復執行。

 

通過跳過 Effect 進行性能優化,在某些情況下,每次渲染后都執行清理或者執行 effect 可能會導致性能問題。在 class 組件中,我們可以通過在 componentDidUpdate 中添加對 prevProps 或 prevState 的比較邏輯解決:

 

 

  1.  
    componentDidUpdate(prevProps, prevState) {
  2.  
    if (prevState.count !== this.state.count) {
  3.  
    document.title = `You clicked ${this.state.count} times`;
  4.  
    }
  5.  
    }

 

這是很常見的需求,所以它被內置到了 useEffect 的 Hook API 中。如果某些特定值在兩次重渲染之間沒有發生變化,你可以通知 React 跳過對 effect 的調用,只要傳遞數組作為 useEffect 的第二個可選參數即可:

 

 

  1.  
    useEffect(() => {
  2.  
    document.title = `You clicked ${count} times`;
  3.  
    }, [count]); // 僅在 count 更改時更新

 

你已經學習了 State Hook 和 Effect Hook,將它們結合起來你可以做很多事情了。它們涵蓋了大多數使用 class 的用例。

 

 

 

 

 

 

 

 

 

 

 

 

640?wx_fmt=png

 


免責聲明!

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



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