當我們在 Component 裡面寫 useState
的時候,這就會在 Component 裡面建立一個專屬該 component 的 state 資料,會記憶在 Component 裡面。但我們其實也可以透過 Component 的 props
,傳給 Child Component,讓 Component 之間共享同一個 state,幫助我們有更多元的 UI 呈現。今天的文章就會來介紹什麼時候會共享 state,跟其中一些觀念。
今天的文章參考官方文件的:
官方文件用 折疊區域(Accordion) 當作例子,會有兩個 文字區域 (Panel)可以點擊 Show
按鈕看裡面的內容。當我們在被 Acoordion
這個 Parent Component 包含的 Panel
component 裡宣告 isActive
這個 state,並且 render 兩個不同內容的 Panel
。會發現 isActive
的更新會是各自獨立的,按按鈕之後不會互相影響。
但如果有個使用情境是,一次只會想要一個文字區域展開,但由於操控的 state 在 Panel
自己裡面,所以沒辦法去更新別的地方。這時候我們就會把 state 往上一個 component 提,再透過 props
的傳入去控制 Panel
裡的狀態。
範例就會是這樣:
export default function Accordion() {
const [activeIndex, setActiveIndex] = useState(0);
return (
<>
<h2>Almaty, Kazakhstan</h2>
<Panel
title="About"
isActive={activeIndex === 0}
onShow={() => setActiveIndex(0)}
>
With a population of about 2 million, Almaty is Kazakhstan's largest city. From 1929 to 1997, it was its capital city.
</Panel>
<Panel
title="Etymology"
isActive={activeIndex === 1}
onShow={() => setActiveIndex(1)}
>
The name comes from <span lang="kk-KZ">алма</span>, the Kazakh word for "apple" and is often translated as "full of apples". In fact, the region surrounding Almaty is thought to be the ancestral home of the apple, and the wild <i lang="la">Malus sieversii</i> is considered a likely candidate for the ancestor of the modern domestic apple.
</Panel>
</>
);
}
可以看到把原本在 Panel
裡面的 isActive
先刪掉,再多新增 props isActive
跟 onShow
去操控狀態,最後在 Accordion
這個 Parent component 再建一個 activeIndex
的 state,傳入適當的 isActive
跟 onShow
給 Panel
,這樣就能達成一次只顯示一個文字區域的 UI。
像是這樣把 state 往上提的情況,在 React 的開發裡面非常常見。有時候我們在開發的時候也會發現,component 裡的 state 也許可以從 parent 那邊取得,也會用剛剛的流程把 state 往上抬。
剛剛在介紹 state 的上提的時候,有提到操控與控制等行為。那是因為當 state 存在 component 自身裡面的話,他無法從外部去更新他的狀態,只能從 component 內部自己的操作才能有所改變。而當我們把 state 上提變成需要從外部傳入 props 的時候,他就變成可以根據 props 的值去控制 component 裡的行為。因此就會分成 控制 跟 非控制。
Controlled component 的好處是它具有彈性,可以透過 props 去做客制化的行為。
Uncontrolled component 的優點則是它可以很簡單的使用,不需要去多處理一些設定。
這兩種 component 沒有特別一定要用哪一種,會根據 UI 情境挑選最適合的選項,甚至可能還會有兩種一起使用的 component 發生(沒傳入 props 的時候使用預設行為,但透過傳入 props 變成可以控制)。
另外還有另一種 控制與非控制 component,就是需不需要受到 React 的 state 去控制行為,這種就叫做 controlled component,而如果是直接使用 html 原生行為,像是 form
的提交或是直接操作 DOM 去獲得 input
的值,沒有 React state 的影響就會叫做 uncontrolled component。這在表單的操作時會需要常常思考要用哪一種,但這種的跟前面提到的控制非控制不一樣,在跟別人討論的時候記得要確定對方是在講哪一種。
form 相關的控制非控制可以參考:
今天介紹了如何在 component 之間共享 state 資訊,跟把 state 上提的情境。這在我平常工作也很常會有使用到的情況,大家可以多試試。另外也介紹了控制與非控制的 component,這在開發的時候也是需要思考的觀念,希望有幫助到大家。
今天的文章就到這邊,感謝大家耐心地看完,如果有任何問題與建議歡迎告訴我,明天見,晚安。