<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          React18 的 useEffect 新特性為什么被瘋狂吐槽?

          共 2643字,需瀏覽 6分鐘

           ·

          2022-05-28 05:08

          react18 已經(jīng)出來一段時間了,create-react-app 默認安裝的 React 版本也已經(jīng)是 18+,不知道有沒有小伙伴發(fā)現(xiàn)自己有點看不懂 React 了?

          import?{?useEffect,?useState?}?from?'react'

          function?App?()?{
          ??const?[data,?setData]?=?useState(0)
          ??
          ??useEffect(()?=>?{
          ????setData(preData?=>?preData?+?1)
          ??},?[])
          ??
          ??return?(
          ????<div>{data}div>
          ??)
          }

          看一下這段簡單的代碼,頁面最終展示的數(shù)字是幾?

          1 這樣嗎?我覺得應(yīng)該也是這樣,可事實就是在 React18 里,這并不是預(yù)期效果,最終展示的其實是 2,為什么呢?

          useEffect 的"新特性"

          根據(jù) React 最新的文檔[1] 中對于 useEffect 的介紹得知,之所以我們剛才的例子最終展示的是 2 而不是 1 的原因是,在 dev 環(huán)境下,React 會將每個組件掛載兩次進行測試。測試什么?測試你的 useEffect 有沒有潛在問題

          大家都知道函數(shù)式組件掛載后,會執(zhí)行 useEffect 定義的副作用;在組件卸載時,會執(zhí)行 useEffect return 出來的回調(diào)執(zhí)行一些組件卸載時的行為,即:

          function?App?()?{
          ??useEffect(()?=>?{
          ????console.log('組件掛載了')
          ????return?()?=>?{
          ??????console.log('組件卸載了')
          ????}
          ??},?[])
          ??
          ??return?(
          ????<div>useEffectdiv>
          ??)
          }

          從組件掛載到卸載就會依次打?。?/p>

          組件掛載了
          組件卸載了

          而在 React18 里,是這樣打印的:

          組件掛載了
          組件卸載了
          組件掛載了

          按照文檔里所說的,之所有這么做的,是為了通過掛載兩次組件來提早發(fā)現(xiàn)你的問題,例如:

          import?{?useEffect,?useState?}?from?'react'

          function?App?()?{
          ??const?[data,?setData]?=?useState(0)
          ??
          ??useEffect(()?=>?{
          ????setInterval(()?=>?{
          ??????setData(preData?=>?preData?+?1)
          ????},?1000)
          ??},?[])
          ??
          ??return?(
          ????<div>{data}div>
          ??)
          }

          這段代碼時很多剛使用 React 的同學(xué)經(jīng)常會犯的錯誤,在 useEffect 里定義了個定時器,但沒有在任何地方去清除它,所以即使在組件卸載了,這個定時器仍然還在運作,不光造成了內(nèi)存泄漏,還可能會導(dǎo)致程序出現(xiàn)問題

          所以就基于這段錯誤的代碼,React18 執(zhí)行 掛載 => 卸載 => 掛載,你就會發(fā)現(xiàn),實際是有兩個定時器在跑的,所以原本你想每秒 data + 1,變成了每秒 data + 2,如此明顯的問題一下就被我們發(fā)現(xiàn)了

          那正確的做法就是在 useEffectreturn 一個用于卸載時執(zhí)行的回調(diào)函數(shù):

          import?{?useEffect,?useState?}?from?'react'

          function?App?()?{
          ??const?[data,?setData]?=?useState(0)
          ??
          ??useEffect(()?=>?{
          +???const?timer?=?setInterval(()?=>?{
          ??????setData(preData?=>?preData?+?1)
          ????},?1000)
          ?
          +???return?()?=>?clearInterval(timer)
          ??},?[])
          ??
          ??return?(
          ????
          {data}

          ??)
          }

          這樣就沒有問題了。謝謝 React18 這個"獨特"的新特性(手動狗頭)

          單單基于這個出發(fā)點,我覺得是非常好的,能幫我們提早發(fā)現(xiàn)問題,解決問題,而不是等發(fā)到線上后造成了性能問題,回過頭來再逐一排查。而且這只會在開發(fā)環(huán)境才會掛載兩次,生產(chǎn)環(huán)境還是正常的

          但真的是個完美的特性嗎?根據(jù)網(wǎng)友的吐槽和我目前使用下來的感受,給我們造成的麻煩可能大于它本身的好處了

          即使我的 useEffect 里根本沒有需要在卸載時清理的對象,它也會被執(zhí)行兩次,比如請求兩次、賦值兩次 ... 這似乎是給我們造成了不少的負擔(dān)啊,不知道的以為是別的地方出了 bug 呢!

          關(guān)閉特性

          我也可以手動關(guān)閉這個特性,找到入口文件 main.tsx,把 StrictMode 標簽給去掉就好了

          mport?React?from?'react'
          import?ReactDOM?from?'react-dom/client'
          import?App?from?'./App'
          import?'./index.css'

          ReactDOM.createRoot(document.getElementById('root')!).render(
          -?
          ????
          -?
          )

          不過這樣也把其它的提示給一并干掉了,其實我是不想這么做的

          只是這樣?

          有很多人都在吐槽著!比如:初始化時 useEffect 會造成兩次請求的話,似乎我們也不該在 useEffect 中發(fā)起請求?

          然而 Dan 給出的解釋就是說,你應(yīng)該在服務(wù)端渲染時就請求到數(shù)據(jù),而不是在客戶端渲染掛載了 DOM 后才請求數(shù)據(jù)

          其實 React18 將在之后推出一些別的功能,這個模擬組件重新掛載的特性只是為之后的功能做準備的,具體是什么功能呢?類似于 Vue 的 KeepAlive[2]

          最后

          簡單總結(jié)一下:這個特性出發(fā)點是好的,同時也是為了之后的新特性做準備。但推出這個功能的同時也要考慮一下開發(fā)者的體驗(起碼是大部人的開發(fā)體驗),不然真的是得不償失。

          對于 useEffect 這個新特性,你怎么看?歡迎在評論區(qū)留言!

          參考資料

          [1]

          React 最新的文檔: https://beta-reactjs-org-git-effects-fbopensource.vercel.app/learn/synchronizing-with-effects

          [2]

          KeepAlive: https://vuejs.org/guide/built-ins/keep-alive.html#basic-usage

          瀏覽 49
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产免费一级视频 | 久久超| 艹屄网 | 免费av中文字幕 免费A片视频网站 | 高清免费在线中文Aⅴ |