日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

javapanel根据内部组件_[译]避免在unmounted组件上调用setState

發布時間:2023/12/10 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 javapanel根据内部组件_[译]避免在unmounted组件上调用setState 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

[譯]避免在unmounted組件上調用setState

原文 : https://www.robinwieruch.de/react-warning-cant-call-setstate-on-an-unmounted-component

很多人在開發 React 的過程中,會遇到下面這些警告。github上很多issue都和這些警告相關。因此,我想在這篇文章里,講講下面這兩個警告的原因和應對方法。

  • 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.

在大多數情況下,警告并不會讓你的應用崩潰。但你還是應該關注一下這些警告。比如,如果你不能妥善處理你的組件state問題,上面這些警告將會導致性能問題。讓我們進一步來看看這些警告到底是怎么回事。

當你的組件已經unmount之后,如果你還在該組件上調用 this.setState(),那么上面的警告就會出現。有下面幾種情況,都會觸發組件的unmount:

  • 根據 React 的條件渲染 ,你不再渲染某個組件了發生了頁面跳轉,比如使用了 React Router,從一個頁面跳轉到了另一個頁面

當組件被unmount之后,你仍然可能會調用該組件的 this.setState() 方法,比如你在該組件內部有異步操作(通常是網絡請求)發生,在異步操作結束之后,你可能需要更新該組件的state。下面是這種情況發生的例子:

  • 你在組件內,向某個API接口發起了異步請求,在請求結束之前,你的組件被unmount了。在這之后,請求響應,你需要根據響應的內容,調用組件的 this.setState() 來更新狀態,然而,這時該組件已經被unmount了你在組件內部綁定了一個事件回調函數,但是沒有在組件的 componentWillUnmount 里取消事件綁定。在組件被unmount之后,該事件回調函數可能會被調用你在組件內部有一個定時器(interval),你在計時器的回調函數里,調用了 this.setState()來更新組件狀態。如果你忘記了在 componentWillUnmount 里清除掉定時器,那么就會像上面那樣,在unmount的組件上更新state

出現上面的警告時,最壞的情況是什么呢?它將給你的react應用帶來性能上的負面影響,因為上述情況會導致你的應用存在內存泄露問題。如果你只是在某個組件里,在組件unmount之后還調用了 this.setState ,可能不會有太大的問題。但是,如果你的應用了有很多組件都有這個問題,那你的react應用性能將會收到明顯的的影響。當然了,這也不是最壞的情況。最壞的情況發生在你忘記了取消事件綁定或者清除計時器。想象一下,你在組件內啟動了定時器,每秒都會更新組件的state,之后組件被unmount了。如果你忘記了清除這個定時器,那么你可能會感受到,你的應用性能會被明顯的拖慢。

怎樣避免在定時器/事件回調里調用unmounted組件的setState

你可能已經注意到了,在大多數情況下,如果我們能夠在組件的 componentWillUnmount里正確的處理定時器、事件監聽,那么上面的警告是能夠避免的。比如,在 componentWillUnmount里,清除定時器,取消事件綁定等。

在這個 定時器demo 里,你可以試試不清除掉定時器的情況。

怎樣避免在異步請求里調用unmounted組件的setState

在上面的例子里,我們針對定時器、事件綁定,在 componentWillUnmount里,相應的清除了定時器、取消了事件綁定。實時上,我們沒有理由不這樣做。

那么,在react組件里的異步請求的情況下,該怎么避免上面的問題呢?我們經常會在react組件里發起異步請求,在網絡結束之后,調用 this.setState() 來更新組件state。然而,在我們異步請求結束之前,組件就已經被unmount了,腫么辦?上面的警告會出現在你的瀏覽器控制臺里,因為react不能將state更新到已經unmount的組件上。看個例子:

class News extends Component { constructor(props) { super(props); this.state = { news: [], }; } componentDidMount() { axios .get('https://hn.algolia.com/api/v1/search?query=react') .then(result => this.setState({ news: result.data.hits, }), ); } render() { return (
  • {this.state.news.map(topic => (
  • {topic.title} ))}
); }}

要想避免這個問題,你可以在組件unmount的時候,中斷網絡請求,或者在網絡結束時,避免調用 this.setState() 。然而,大多數基于 Promise的網絡請求庫,都沒有提供中斷網絡請求的功能,因此我們需要自己在組件類上,增加一個類的 實例屬性 來標記當前組件是否已經mount了。這個標記默認是 false 的,之后在組件的 componentDidMount里,標記設置為 true;在組件的 componentWillUnmount里,設置為 false。通過這個屬性,我們能夠知道當前組件是否處于mount之后。這個屬性 不會 受 this.setState()的影響,因為它是 實例屬性,我們能夠直接在組件實例上訪問它,不需要經過react組件的 this.state。因為它不在組件的state上,我們修改這個屬性,也就 不會 觸發組件重新render了。看下修改之后的代碼:

class News extends Component { _isMounted = false; constructor(props) { super(props); this.state = { news: [], }; } componentDidMount() { this._isMounted = true; axios .get('https://hn.algolia.com/api/v1/search?query=react') .then(result => { if (this._isMounted) { this.setState({ news: result.data.hits, }); } }); } componentWillUnmount() { this._isMounted = false; } render() { // 省略相同代碼 ... }}

現在,即使在組件unmount之后,網絡請求才結束,我們通過 this._isMounted 這個標記,就能避免在網絡請求結束后,調用被unmounted組件的 this.setState()方法。這個demo地址的源碼,在 這個github倉庫 。

通過引入 this._isMounted 這個標記,不會影響到你所使用的網絡請求庫,不管你是使用瀏覽器原生的 fetch 還是 第三方庫比如 axios,都沒有問題。

譯者注:幾年前接觸react的時候,找到的方法,就和文章里的一樣,本來以為會有其他更高大上的東東的……

總結

以上是生活随笔為你收集整理的javapanel根据内部组件_[译]避免在unmounted组件上调用setState的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。