React中useEffect使用


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

 

class Example extends React.Component {    
  constructor(props) {    
    super(props);    
    this.state = {    
      count: 0    
    };    
  }

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

  

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

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

 

class Example extends React.Component {    
  constructor(props) {    
    super(props);    
    this.state = {    
      count: 0    
    };    
  }    
  componentDidMount() {    
    document.title = `You clicked ${this.state.count} times`;    
  }    
  componentDidUpdate() {    
    document.title = `You clicked ${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 的示例

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> ); }

 

 

使用 Hook 的示例

 

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>    
  );    
}

 

 

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

 

數據獲取,設置訂閱以及手動更改 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>    
}

 

 

useEffect(effect: React.EffectCallback, inputs?: ReadonlyArray<any> | undefined)

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

 

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

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

 

 

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

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

 

 

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


免責聲明!

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



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