iT邦幫忙

2025 iThome 鐵人賽

DAY 15
0

昨天對 State 有了初步介紹,之後的官方文件其實也有對 State 直接有一個大 章節,會留在後面的篇章。今天想講更多 useState 相關的內容,跟一些他的使用的注意事項。

讓 Component 使用多個 state

當我們使用 Component 來產生 UI 的時候,有時候會不只用到一個 state 來管理各種狀態與資料,這時候就可以使用多個 useState 來管理。通常要使用多個情況,會是資料彼此比較不需要同時更新的時候,像是文章裡的範例,可以寫成選擇顯示第幾個文章的 index,跟顯示更多的 showMore 這兩個,我們也可以把他們寫在一起變成一個 object

const [galleryInfo, setGallery] = useState({ index: 0, showMore: false }) 

不過通常是會常同時更新資料的時候才會寫在一起,因為我們在 set 更新的時候會把需要的值都重新設定。
之後的文章 選擇 State 架構 會有更多 state 架構相關的小技巧,有興趣可以先看看。

State 是獨立(isolated)且私密(private)的

State 是 Component 的 loacl 資料,會只屬於那個 Component,這是指 state 會跟著 render 的那個 component,所以當我們重複使用多個同一個 Component 的話,他們彼此的 state 會是獨立的,也就是說彼此之間的 local 資料會只屬於他們自己的,不會互相影響。
文章中使用兩個 Gallery component,所以同時顯示兩個 UI 畫面,當我們按其中一個按鈕時,只又被按的那個 Component 的畫面會改變,另一個的就還是保持原樣,如果我們想要分享同一個 state 的話,就需要在最近一個相關的 Parent Component useState 後,當作 prop 傳給想要使用的 child component。拿官方文章的例子,就可以寫成:

export default function Page() {
  const [showMore, setShowMore] = useState(false);
  
  return (
    <div className="Page">
      <Gallery showMore={showMore} setShowMore={setShowMore} />
      <Gallery showMore={showMore} setShowMore={setShowMore} />
    </div>
  );
}

然後再把 GalleryshowMore useState 拿掉,改寫成傳入 prop

export function Gallery({ showMore, setShowMore={setShowMore }}) {
  // ... same code
}

這樣當我們點選 Show Details 按鈕就會兩個同時顯示更多資訊。

使用 useState 規則

不知道有沒有注意到,在寫 useState 的時候,都會在 Component 的最上方,這是因為在 render 的時候,React 會用陣列管理 component 的 state,會需要在一開始就照著 useState 的順序一個一個把正確的值回傳。在更新的時候也會透過這個陣列,去更新到正確的 state,所以就會有幾個規則:

  1. 一定要使用在 React function component 裡面
  2. 不能使用在條件式、迴圈或是巢狀的 functions

這些規則都是為了不打亂用來管理的陣列,而這個其實不只是適用於 useState,而是全部的 Hooks 都需要遵守,之後會陸續介紹更多的 hooks 的運用。
關於更多管理 hooks 的陣列,可以參考官方文件裡推薦閱讀的:

小結

今天的文章再把 useState 一些相關再多做補充,這也是我們的一個使用到的 Hooks,之後也會很常使用到,希望有讓大家能知道些基本概念。明天的文章會來介紹 React 是怎麼更新網頁畫面的,對我們在設計 React 架構也是十分鐘要。
文章差不多到這邊,感謝大家耐心地看完,有任何建議跟問題都歡迎跟我說,明天見,晚安。


上一篇
Day 14 - State: Component 的記憶
下一篇
Day 16 - Render 和 Commit
系列文
重溫 React 官方文件回到最初的起點20
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言