避免已卸載的組件繼續(xù)調(diào)用setState()

本文轉(zhuǎn)載自我的個(gè)人博客彤守。

這是一篇譯文毯侦,原文在這里。有興趣的同學(xué)可以直接閱讀原文具垫,寫的很好侈离。圖省事的同學(xué)可以直接看我的精簡的譯文。

相信很多react初學(xué)者都遇到過以下兩個(gè)警告(warnings)

  • Warning: Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component. This is a no-op.

  • Warning: Can’t call setState (or forceUpdate) on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.

一般來說警告并不會(huì)讓你的程序崩潰筝蚕,但是它會(huì)降低程序的性能卦碾,比如我們上面提到的這兩個(gè)警告就是這樣铺坞。下面讓我們來討論一下這兩個(gè)警告到底講的是什么吧。

當(dāng)一個(gè)已經(jīng)被卸載(unmounted)的組件調(diào)用setState()方法時(shí)洲胖,你就會(huì)遇到以上兩個(gè)警告济榨。一般來說,有兩種情況會(huì)導(dǎo)致組件的卸載:

  1. 通過條件渲染的組件绿映,其渲染條件從達(dá)到變?yōu)闆]有達(dá)到擒滑,導(dǎo)致已渲染的組件的卸載
  2. 通過路由手段路由到別的組件,導(dǎo)致原組件被卸載

當(dāng)組件被卸載后叉弦,被卸載的組件內(nèi)的某些異步邏輯可能在組件被卸載后調(diào)用了setState()企圖更新組件內(nèi)的state丐一,通常有三種場景可能會(huì)發(fā)生這種情況:

  1. 你對(duì)某個(gè)API提交了一個(gè)異步請(qǐng)求,組件在收到響應(yīng)前就被卸載了淹冰,收到響應(yīng)之后調(diào)用了setState()企圖更新state库车,但這個(gè)時(shí)候組件早就被卸載了。
  2. 你為組件添加了監(jiān)聽事件樱拴,但是沒有在componentWillUnmount()里移除這個(gè)監(jiān)聽事件柠衍,當(dāng)組件移除以后監(jiān)聽的事件被觸發(fā)。
  3. 你在類似于setInterval()的函數(shù)里調(diào)用了setState()疹鳄,但是沒有在componentWillUnmount()里移除這些函數(shù)拧略。

那么在遇到以上兩個(gè)警告時(shí)我們怎么樣才能解決他們呢?

避免 intervals/listeners 在已卸載的組件中調(diào)用 setState()

對(duì)于上面提到的三種情況中的后兩種情況瘪弓,我們只需要在componentWillUnmount()生命周期鉤子里將intervals/listeners移除就可以了。具體操作可以參考這個(gè)例子禽最。

避免異步請(qǐng)求在已卸載的組件中調(diào)用 setState()

為了避免異步請(qǐng)求在已卸載的組件中調(diào)用setState()腺怯,我們可以在請(qǐng)求收到響應(yīng)后添加一個(gè)判斷條件,判斷此時(shí)組件有沒有被卸載川无,如果沒有卸載再繼續(xù)執(zhí)行之后的代碼(比如setState())呛占。具體實(shí)現(xiàn)如下:

  class News extends Component {
    //添加一個(gè) class field 記錄組件有沒有被卸載,初始化為false懦趋,表示已卸載
    _isMounted = false;

    constructor(props) {
      super(props);

      this.state = {
        news: [],
      };
    }

    componentDidMount() {
      //組件在被掛載后將_isMounted的值更新為true晾虑,表示已掛載
      this._isMounted = true;

      axios
        .get('https://hn.algolia.com/api/v1/search?query=react')
        .then(result => {
          //通過_isMounted判斷組件有沒有被卸載
          if (this._isMounted) {
            this.setState({
              news: result.data.hits,
            });
          }
        });
    }

    componentWillUnmount() {
      //在組件被卸載時(shí)將_isMounted更新為false,表示組件已卸載
      this._isMounted = false;
    }

    render() {
      ...
    }
  }

一個(gè)小插曲仅叫,關(guān)于class field是什么帜篇,給大家兩個(gè)例子,可以先體會(huì)下用class field和不用的區(qū)別诫咱,以后有時(shí)間笙隙,我再寫一篇專門關(guān)于class field的文章。

不用class field:

  class IncreasingCounter {
    constructor() {
      this._count = 0;
    }
    get value() {
      console.log('Getting the current value!');
      return this._count;
    }
    increment() {
      this._count++;
    }
  }

class field:

  class IncreasingCounter {
    _count = 0;
    get value() {
      console.log('Getting the current value!');
      return this._count;
    }
    increment() {
      this._count++;
    }
  }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末坎缭,一起剝皮案震驚了整個(gè)濱河市竟痰,隨后出現(xiàn)的幾起案子签钩,更是在濱河造成了極大的恐慌,老刑警劉巖坏快,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件铅檩,死亡現(xiàn)場離奇詭異,居然都是意外死亡莽鸿,警方通過查閱死者的電腦和手機(jī)昧旨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來富拗,“玉大人臼予,你說我怎么就攤上這事】谢Γ” “怎么了粘拾?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長创千。 經(jīng)常有香客問我缰雇,道長,這世上最難降的妖魔是什么追驴? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任械哟,我火速辦了婚禮,結(jié)果婚禮上殿雪,老公的妹妹穿的比我還像新娘暇咆。我一直安慰自己,他們只是感情好丙曙,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布爸业。 她就那樣靜靜地躺著,像睡著了一般亏镰。 火紅的嫁衣襯著肌膚如雪扯旷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天索抓,我揣著相機(jī)與錄音钧忽,去河邊找鬼。 笑死逼肯,一個(gè)胖子當(dāng)著我的面吹牛耸黑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播汉矿,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼崎坊,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了洲拇?” 一聲冷哼從身側(cè)響起奈揍,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤曲尸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后男翰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體另患,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年蛾绎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了昆箕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡租冠,死狀恐怖鹏倘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情顽爹,我是刑警寧澤纤泵,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站镜粤,受9級(jí)特大地震影響捏题,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜肉渴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一公荧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧同规,春花似錦循狰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至朱灿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間钠四,已是汗流浹背盗扒。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留缀去,地道東北人侣灶。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像缕碎,于是被迫代替她去往敵國和親褥影。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容