亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

React 數(shù)據(jù)獲取條件競(jìng)爭(zhēng)原理解析

 更新時(shí)間:2023年01月29日 15:04:10   作者:KooFE  
這篇文章主要為大家介紹了React 數(shù)據(jù)獲取條件競(jìng)爭(zhēng)原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

本文源于翻譯 Fetching data in React: the case of lost Promises 由公眾號(hào) ikoofe 完成翻譯。

在某些場(chǎng)景里,前端開(kāi)發(fā)同學(xué)會(huì)無(wú)意識(shí)的編寫(xiě)出一些看似正確的代碼,這些代碼能夠通過(guò)所有測(cè)試以及代碼審查,但是在實(shí)際執(zhí)行時(shí)會(huì)導(dǎo)致應(yīng)用程序出現(xiàn)一些意想不到的問(wèn)題:頁(yè)面上的數(shù)據(jù)毫無(wú)規(guī)律地隨機(jī)展示出來(lái)、搜索出的結(jié)果與查詢條件不匹配、切換選項(xiàng)卡的導(dǎo)航時(shí)出現(xiàn)錯(cuò)誤的內(nèi)容。

當(dāng)然,我們并不希望發(fā)生這些問(wèn)題,那么如何避免這些問(wèn)題呢?本文將繼續(xù)討論 React 數(shù)據(jù)獲取的一些方法和原理,并深入了解 Promise 在數(shù)據(jù)獲取時(shí)如何導(dǎo)致了條件競(jìng)爭(zhēng)(race conditions)以及如何避免它們。

Promise 簡(jiǎn)介

在本文正式開(kāi)始之前,我們先了解一下 Promise 以及我們?yōu)槭裁葱枰?Promise。

當(dāng) JavaScript 執(zhí)行代碼時(shí),通常是一步一步地同步執(zhí)行。Promise 是為數(shù)不多的異步執(zhí)行方法之一。有了 Promise,我們就可以直接觸發(fā)一個(gè)任務(wù)并立即進(jìn)入下一步,而無(wú)需等待任務(wù)完成。當(dāng)任務(wù)完成后,Promise 會(huì)通知我們。

數(shù)據(jù)獲取是 Promise 最重要和最廣泛使用的場(chǎng)景之一。不管是直接使用 fetch 還是使用像 axios 這樣的第三方類庫(kù),Promise 的行為都是一樣的。

從代碼的角度來(lái)看,如下所示:

console.log('first step'); // will log FIRST
fetch('/some-url') // create promise here
  .then(() => { // wait for Promise to be done
      // log stuff after the promise is done
      console.log('second step') // will log THIRD (if successful)
    }
  )
  .catch(() => {
    console.log('something bad happened') // will log THIRD (if error happens)
  })
console.log('third step') // will log SECOND

整個(gè)過(guò)程是:在 fetch('/some-url') 中創(chuàng)建一個(gè) Promise,然后在 .then.catch 中處理后續(xù)的事情。當(dāng)然,這個(gè)簡(jiǎn)單的示例只是為了方便大家理解本文的后續(xù)部分。如果要完全掌握 Promise,需要閱讀資料來(lái)了解更多的細(xì)節(jié),本文不做暫不展開(kāi)介紹。

Promise 和條件競(jìng)爭(zhēng)

Promise 會(huì)帶來(lái)?xiàng)l件競(jìng)爭(zhēng)這個(gè)問(wèn)題,下面以一個(gè)簡(jiǎn)單的應(yīng)用頁(yè)面為例展開(kāi)介紹:

頁(yè)面的左側(cè)是選項(xiàng)卡 tabs 的列,切換 tabs 就會(huì)導(dǎo)航到新頁(yè)面并發(fā)送一個(gè)數(shù)據(jù)請(qǐng)求,請(qǐng)求返回的數(shù)據(jù)渲染在右側(cè)。如果快速的來(lái)回切換 tabs 就會(huì)發(fā)現(xiàn)這里存在奇怪問(wèn)題:右側(cè)的內(nèi)容會(huì)閃爍,數(shù)據(jù)看起來(lái)是隨機(jī)出現(xiàn)的。

這個(gè)問(wèn)題是怎么發(fā)生的?讓我們看看頁(yè)面的實(shí)現(xiàn)。頁(yè)面有兩個(gè)部分。一個(gè)是根 App 組件,它管理 “page” 的狀態(tài),并渲染了導(dǎo)航按鈕和實(shí)際的 Page 組件。

const App = () => {
  const [page, setPage] = useState("1");
  return (
    <>
      <!-- left column buttons -->
      <button onClick={() => setPage("1")}>Issue 1</button>
      <button onClick={() => setPage("2")}>Issue 2</button>
      <!-- the actual content -->
      <Page id={page} />
    </div>
  );
};

Page 組件接受 page 的 id 作為屬性,發(fā)送請(qǐng)求以獲取數(shù)據(jù),然后渲染數(shù)據(jù)。Page 組件的實(shí)現(xiàn)(沒(méi)有加載狀態(tài))如下所示:

const Page = ({ id }: { id: string }) => {
  const [data, setData] = useState({});
  // pass id to fetch relevant data
  const url = `/some-url/${id}`;
  useEffect(() => {
    fetch(url)
      .then((r) => r.json())
      .then((r) => {
        // save data from fetch request to state
        setData(r);
      });
  }, [url]);
  // render data
  return (
    <>
      <h2>{data.title}</h2>
      <p>{data.description}</p>
    </>
  );
};

通過(guò) id,我們確定從哪個(gè) url 獲取數(shù)據(jù)。然后我們?cè)趗seEffect 中發(fā)送數(shù)據(jù)請(qǐng)求,并將結(jié)果數(shù)據(jù)存儲(chǔ)在 state 中 —— 這一切都很標(biāo)準(zhǔn)。那么,條件競(jìng)爭(zhēng)和奇怪問(wèn)題是什么原因?qū)е碌哪兀?/p>

條件競(jìng)爭(zhēng)的起因

這一切歸結(jié)為兩件事:Promise 和 React 生命周期。從生命周期的角度來(lái)看,會(huì)發(fā)生這些事情:

  • App 組件被裝載(mounted)
  • Page 組件被裝載,并默認(rèn)的 prop 為 “1”
  • Page 組件中的 useEffect 首次被執(zhí)行

然后 Promise 開(kāi)始執(zhí)行:useEffect 中的 fetch 是一個(gè)promise 異步操作。它負(fù)責(zé)發(fā)送實(shí)際的數(shù)據(jù)請(qǐng)求,而 React 繼續(xù)它自己的工作,而不等待結(jié)果。大約 2s 后數(shù)據(jù)請(qǐng)求完成,在 .then 中調(diào)用 setData 并將數(shù)據(jù)保存在 state 中,Page 組件渲染出最新的數(shù)據(jù),最終我們?cè)谄聊簧峡吹竭@些數(shù)據(jù)。

如果在渲染和完成所有內(nèi)容后,單擊導(dǎo)航按鈕,我們將看到以下事件:

  • App 組件將其狀態(tài)更改為另一個(gè) page
  • state 觸發(fā) App 組件的重新渲染
  • Page 組件也將重新渲染
  • Page 組件中的 useEffect 依賴于 id;由于 id 已變化,將再次觸發(fā) useEffect
  • useEffect 將用新 id 觸發(fā) fecth 請(qǐng)求,大約 2s 后將再次調(diào)用 setData,Page 組件更新,我們?cè)谄聊簧峡吹叫聰?shù)據(jù)

但是,如果 id 第一次變化觸發(fā)的 fetch 尚未返回,這時(shí)單擊導(dǎo)航按鈕切換 tabs 會(huì)發(fā)生什么?

  • App 組件將再次觸發(fā)頁(yè)面的重新渲染
  • useEffect 也將再次被觸發(fā)(id 已發(fā)生變化?。?/li>
  • fetch 將再次被執(zhí)行,React 將一如既往地繼續(xù)工作
  • 這時(shí)第一次數(shù)據(jù)請(qǐng)求完成。它仍然可以訪問(wèn)到 Page 組件的 setData(組件只是被更新,組件仍然是之前的組件)
  • 第一次請(qǐng)求成功后的 setData 將被觸發(fā),Page 組件將使用該次請(qǐng)求的數(shù)據(jù)更新自身
  • 第二次請(qǐng)求完成。它仍然在那里,掛在后臺(tái),就像任何 Promise 一樣。該組件依然使用了同一個(gè) Page 組件的 setData,它將被觸發(fā),Page 再次更新自身,這一次使用的是第二次獲取的數(shù)據(jù)。

條件競(jìng)爭(zhēng)出現(xiàn)了!點(diǎn)擊導(dǎo)航按鈕到新 page 后,我們看到了頁(yè)面內(nèi)容發(fā)生閃爍:首先渲染第一次請(qǐng)求的數(shù)據(jù),然后替換成第二次請(qǐng)求的數(shù)據(jù)。

如果第二次數(shù)據(jù)請(qǐng)求在第一次數(shù)據(jù)請(qǐng)求之前完成,這種效果就更有趣了。我們將首先看到下一頁(yè)的正確內(nèi)容,然后它將被上一頁(yè)的不正確內(nèi)容替換。

解決條件競(jìng)爭(zhēng):強(qiáng)制重新掛載

嚴(yán)格來(lái)說(shuō),這并不是一個(gè)解決方案,它更多的是用來(lái)解釋為什么這些競(jìng)爭(zhēng)條件不會(huì)經(jīng)常發(fā)生,以及為什么在常規(guī)頁(yè)面導(dǎo)航中我們碰不到競(jìng)爭(zhēng)條件。我們用下面的代碼來(lái)實(shí)現(xiàn)上面的功能:

const App = () => {
  const [page, setPage] = useState('issue');
  return (
    <>
      {page === 'issue' && <Issue />}
      {page === 'about' && <About />}
    </>
  )
}

沒(méi)有向下傳遞 prop,Issue 和 About 組件使用各自的 url 來(lái)完成數(shù)據(jù)請(qǐng)求。在 useEffect 中進(jìn)行數(shù)據(jù)獲取,這與之前的實(shí)現(xiàn)方式完全相同:

const About = () => {
  const [about, setAbout] = useState();
  useEffect(() => {
    fetch("/some-url-for-about-page")
      .then((r) => r.json())
      .then((r) => setAbout(r));
  }, []);
  ...
}

這樣在 tabs 導(dǎo)航時(shí)不會(huì)出現(xiàn)競(jìng)爭(zhēng)條件。無(wú)論操作的次數(shù)和速度有多快,應(yīng)用程序都能夠正常運(yùn)行。這是為什么呢?

答案在這里:{page==='issue'&&<issue/>}。當(dāng) page 的值更改時(shí),Issue 和 About 不會(huì)重新渲染,而是重新裝載。當(dāng)值從 issue 更改為 about 時(shí),Issue 組件將自行卸載,About 組件將裝載在它的位置上。

從數(shù)據(jù)獲取的角度來(lái)看:

  • App 組件首先被渲染,然后裝載 Issue 組件并開(kāi)始獲取數(shù)據(jù)
  • 在數(shù)據(jù)請(qǐng)求過(guò)程中導(dǎo)航到下一個(gè)頁(yè)面,App 組件會(huì)卸載 Issue 組件并裝載 About 組件,然后開(kāi)始它自己的數(shù)據(jù)獲取

當(dāng) React 卸載一個(gè)組件時(shí),意味著它已經(jīng)不存在了。徹底消失了,從屏幕上消失了,沒(méi)有人可以訪問(wèn)它,里面發(fā)生的一切,包括它的狀態(tài)都丟失了。與前面的代碼相比,我們?cè)谇懊娴拇a中編寫(xiě)了 <Page id={Page} />,此 Page 組件從未被卸載,我們只是在導(dǎo)航時(shí)重新使用它。

所以回到卸載的場(chǎng)景。當(dāng) Issue 的數(shù)據(jù)請(qǐng)求在 About 組件上完成時(shí),Issue 組件的 .then 將嘗試調(diào)用其 setIssue 來(lái)設(shè)置 state。但組件已經(jīng)不存在了,從 React 的角度來(lái)看,它已經(jīng)不存在。因此,這個(gè) Promise 也將消失,它得到的數(shù)據(jù)也隨之消失。

順便提一下,你還記得曾經(jīng)有一個(gè)警告 “無(wú)法對(duì)未安裝的組件執(zhí)行React 狀態(tài)更新” 嗎?在組件消失之后完成異步操作(如數(shù)據(jù)獲?。?,會(huì)出現(xiàn)這個(gè)警告。當(dāng)然,現(xiàn)在這個(gè)警告已經(jīng)被 React 刪除掉了。

無(wú)論如何,理論上,這種方法可以用于解決的條件競(jìng)爭(zhēng)問(wèn)題:我們所需要做的是在導(dǎo)航變化時(shí)強(qiáng)制重新裝載 Page 組件。為此,我們可以使用 “key” 屬性:

<Page id={page} key={page} />

但是,并不推薦使用這個(gè)方案來(lái)解決條件競(jìng)爭(zhēng)問(wèn)題,它會(huì)引起一些潛在問(wèn)題:可能會(huì)使性能受到影響,焦點(diǎn)和狀態(tài)會(huì)出現(xiàn)意外錯(cuò)誤,以及觸發(fā)不必要的 useEffect。它并沒(méi)有從根本上解決問(wèn)題,而是將問(wèn)題掩蓋起來(lái)。但在某些場(chǎng)景下,如果小心使用,也不失為一種解決問(wèn)題的方法。

解決條件競(jìng)爭(zhēng):丟棄錯(cuò)誤數(shù)據(jù)

一種解決條件競(jìng)爭(zhēng)更友好的方法,是確保傳入到 .then callback 的數(shù)據(jù)與當(dāng)前被 “選中” 的 id 匹配;而不是清除整個(gè)已存在的 Page 組件。

如果返回的數(shù)據(jù)中包括了用于生成 url 的 “id”,我們可以比較它們是否一致。如果它們不一致,則忽略它們。這里需要做的是,要跳出 React 生命周期和函數(shù)的本地作用域,在 useEffect 訪問(wèn)到最新的 id。React ref 非常適合這個(gè)場(chǎng)景:

const Page = ({ id }) => {
  // create ref
  const ref = useRef(id);
  useEffect(() => {
    // update ref value with the latest id
    ref.current = id;
    fetch(`/some-data-url/${id}`)
      .then((r) => r.json())
      .then((r) => {
        // compare the latest id with the result
        // only update state if the result actually belongs to that id
        if (ref.current === r.id) {
          setData(r);
        }
      });
  }, [id]);
}

如果返回的數(shù)據(jù)結(jié)果中沒(méi)有包含 id,我們可以比較 url:

const Page = ({ id }) => {
  // create ref
  const ref = useRef(id);
  useEffect(() => {
    // update ref value with the latest url
    ref.current = url;
    fetch(`/some-data-url/${id}`)
      .then((result) => {
        // compare the latest url with the result's url
        // only update state if the result actually belongs to that url
        if (result.url === ref.current) {
          result.json().then((r) => {
            setData(r);
          });
        }
      });
  }, [url]);
}

解決條件競(jìng)爭(zhēng):丟棄之前的數(shù)據(jù)

如果不喜歡上面的解決方案,或者認(rèn)為使用 ref 來(lái)做這樣的事情。還有另一種方法:useEffect 有一個(gè)叫做 “cleanup” 的清除函數(shù),在這個(gè)函數(shù)中我們可以清理訂閱之類的東西。在我們的場(chǎng)景中可以用來(lái)控制數(shù)據(jù)獲取。它的語(yǔ)法如下:

// normal useEffect
useEffect(() => {
  // "cleanup" function - function that is returned in useEffect
  return () => {
    // clean something up here
  }
// dependency - useEffect will be triggered every time url has changed
}, [url]);

“cleanup” 的函數(shù)在組件卸載后執(zhí)行,或者在每次依賴項(xiàng)變化引起重新渲染之前運(yùn)行。因此,重新渲染期間的執(zhí)行順序如下:

  • url 發(fā)生變化
  • 觸發(fā) “cleanup” 函數(shù)
  • useEffect 的實(shí)際內(nèi)容被觸發(fā)

利用 JavaScript 函數(shù)和閉包,我們可寫(xiě)出這樣的代碼:

useEffect(() => {
  // local variable for useEffect's run
  let isActive = true;
  // do fetch here
  return () => {
    // local variable from above
    isActive = false;
  }
}, [url]);

我們引入了一個(gè)局部布爾變量 isActive,并在 useEffect 運(yùn)行時(shí)將其設(shè)置為 true,在 “cleanup” 清理時(shí)將其設(shè)為 false。每次重新渲染時(shí)都會(huì)重新創(chuàng)建 useEffect 中的函數(shù),因此最近一次 useEffect 運(yùn)行的 isActive 將始終重置為 true。但是在它之前運(yùn)行的 “cleanup” 函數(shù)仍然可以訪問(wèn)前一個(gè)函數(shù)的作用域,它會(huì)將其重置為 false。這也是 JavaScript 閉包的工作原理。

fetch Promise 雖然是異步的,但仍然只存在于該閉包中,并且只能訪問(wèn) useEffect 運(yùn)行的局部變量。因此,當(dāng)我們?cè)?.then 回調(diào)中檢查 isActive 布爾值時(shí),只有在最近的一次運(yùn)行中,尚未執(zhí)行清理函數(shù),才會(huì)將變量設(shè)置為 true。所以現(xiàn)在需要做的只是檢查是否處于活動(dòng)的閉包中,如果是,則設(shè)置狀態(tài)。如果不是,什么都不做,數(shù)據(jù)將再次憑空消失。

useEffect(() => {
    // set this closure to "active"
    let isActive = true;
    fetch(`/some-data-url/${id}`)
      .then((r) => r.json())
      .then((r) => {
        // if the closure is active - update state
        if (isActive) {
          setData(r);
        }
      });
    return () => {
      // set this closure to not active before next re-render
      isActive = false;
    }
  }, [id]);

解決條件競(jìng)爭(zhēng):取消之前的請(qǐng)求

如果覺(jué)得在 React 生命周期的上下文中處理 JavaScript 閉包太復(fù)雜,那么還有另一種解決問(wèn)題的方法。

我們可以取消之前的所有請(qǐng)求,而不是清理或比較數(shù)據(jù)結(jié)果。如果它們永遠(yuǎn)都不會(huì)完成數(shù)據(jù)請(qǐng)求,那么也就永遠(yuǎn)不會(huì)使用這些過(guò)時(shí)數(shù)據(jù),條件競(jìng)爭(zhēng)的問(wèn)題也就不復(fù)存在。

在這里,我們可以使用 AbortController,實(shí)現(xiàn)的代碼也相對(duì)比較簡(jiǎn)單:在 useEffect 中創(chuàng)建 AbortController 并在清理函數(shù)中調(diào)用 .abort()。

useEffect(() => {
    // create controller here
    const controller = new AbortController();
    // pass controller as signal to fetch
    fetch(url, { signal: controller.signal })
      .then((r) => r.json())
      .then((r) => {
        setData(r);
      });
    return () => {
      // abort the request here
      controller.abort();
    };
  }, [url]);

在每次重新渲染時(shí),正在進(jìn)行的請(qǐng)求將被取消,只允許最新的數(shù)據(jù)請(qǐng)求被解析并更新到 state。

中止正在進(jìn)行的請(qǐng)求,會(huì)導(dǎo)致 Promise 被 reject,因此我們需要捕獲錯(cuò)誤以消除控制臺(tái)中的可怕警告。正確處理 Promise reject 是一個(gè)很好的開(kāi)發(fā)習(xí)慣,這是任何場(chǎng)景都下都應(yīng)該做的事情,與是否使用 AbortController 無(wú)關(guān)。

由 AbortController 引起的 reject 會(huì)拋出的特定類型的錯(cuò)誤,因此很容易將它與其它常規(guī)錯(cuò)誤區(qū)分開(kāi)。

fetch(url, { signal: controller.signal })
  .then((r) => r.json())
  .then((r) => {
    setData(r);
  })
  .catch((error) => {
    // error because of AbortController
    if (error.name === 'AbortError') {
      // do nothing
    } else {
      // do something, it's a real error!
    }
  });

Async/await 會(huì)改變什么嗎?

Async/await 只是編寫(xiě) Promise 的語(yǔ)法糖。從執(zhí)行的角度來(lái)看,它們只是轉(zhuǎn)換為 “同步” 函數(shù),但不會(huì)改變它們的異步特性。下面的 Promise 代碼:

fetch('/some-url')
  .then(r => r.json())
  .then(r => setData(r));

與下面 async/await 代碼等價(jià):

const response = await fetch('/some-url');
const result = await response.json();
setData(result);

使用 async/await 代替 “傳統(tǒng)”的 Promise,同樣會(huì)存在條件競(jìng)爭(zhēng)問(wèn)題,前面介紹的解決方案也依然適用,只是語(yǔ)法略有差異。

以上就是React 數(shù)據(jù)獲取條件競(jìng)爭(zhēng)原理解析的詳細(xì)內(nèi)容,更多關(guān)于React 數(shù)據(jù)獲取條件競(jìng)爭(zhēng)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 深入了解React中的虛擬DOM

    深入了解React中的虛擬DOM

    歡迎來(lái)到今天的探險(xiǎn)之旅!在這篇博客中,我們將深入了解 React 中神奇的虛擬DOM,并通過(guò)一個(gè)簡(jiǎn)單的例子來(lái)揭開(kāi)其神秘面紗,文中通過(guò)代碼示例也講解非常詳細(xì),感興趣的朋友可以參考下
    2024-01-01
  • React實(shí)現(xiàn)Excel文件的導(dǎo)出與在線預(yù)覽功能

    React實(shí)現(xiàn)Excel文件的導(dǎo)出與在線預(yù)覽功能

    這篇文章主要為大家詳細(xì)介紹了如何利用?React?18?的強(qiáng)大功能,演示如何使用?React?18?編寫(xiě)?Excel?文件的導(dǎo)出與在線預(yù)覽功能,需要的小伙伴可以參考下
    2023-12-12
  • 基于React?Hooks的小型狀態(tài)管理詳解

    基于React?Hooks的小型狀態(tài)管理詳解

    本文主要介紹一種基于?React?Hooks?的狀態(tài)共享方案,介紹其實(shí)現(xiàn),并總結(jié)一下使用感受,目的是在狀態(tài)管理方面提供多一種選擇方式。感興趣的小伙伴可以了解一下
    2021-12-12
  • React?組件傳?children?的各種案例方案詳解

    React?組件傳?children?的各種案例方案詳解

    自定義組件的時(shí)候往往需要傳?children,由于寫(xiě)法比較多樣,我就總結(jié)了一下,要自定義的組件其中包含一個(gè)?title?和一個(gè)?children,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2023-10-10
  • ReactQuery?渲染優(yōu)化示例詳解

    ReactQuery?渲染優(yōu)化示例詳解

    這篇文章主要為大家介紹了ReactQuery?渲染優(yōu)化示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • Rect Intersection判斷兩個(gè)矩形是否相交

    Rect Intersection判斷兩個(gè)矩形是否相交

    這篇文章主要為大家介紹了Rect Intersection判斷兩個(gè)矩形是否相交的算法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • 如何去除富文本中的html標(biāo)簽及vue、react、微信小程序中的過(guò)濾器

    如何去除富文本中的html標(biāo)簽及vue、react、微信小程序中的過(guò)濾器

    這篇文章主要介紹了如何去除富文本中的html標(biāo)簽及vue、react、微信小程序中的過(guò)濾器,在vue及react中經(jīng)常會(huì)遇到,今天通過(guò)實(shí)例代碼給大家講解,需要的朋友可以參考下
    2018-11-11
  • react中的useEffect()的使用詳解

    react中的useEffect()的使用詳解

    useEffect()是react中的hook函數(shù),作用是用于創(chuàng)建由渲染本身引起的操作,介紹了依賴項(xiàng)數(shù)組不同的區(qū)別,對(duì)react useEffect()使用相關(guān)知識(shí)感興趣的朋友一起看看吧
    2024-05-05
  • react中常見(jiàn)hook的使用方式

    react中常見(jiàn)hook的使用方式

    這篇文章主要介紹了react中常見(jiàn)hook的使用方式與區(qū)別,幫助大家更好的理解和學(xué)習(xí)使用react,感興趣的朋友可以了解下
    2021-04-04
  • Yarn安裝項(xiàng)目依賴報(bào)error?An?unexpected?error?occurred:?“XXXXX:ESOCKETTIMEOUT”問(wèn)題解決

    Yarn安裝項(xiàng)目依賴報(bào)error?An?unexpected?error?occurred:?“XXXXX:E

    這篇文章主要為大家介紹了Yarn安裝項(xiàng)目依賴報(bào)error?An?unexpected?error?occurred:?“XXXXX:ESOCKETTIMEOUT”問(wèn)題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03

最新評(píng)論