當我們在設計某些功能時,會需要把值暫時保存起來並存至變數供日後使用,state就像component裡的變數,當UI要顯示某個state,就可以取用當下紀錄的狀態,要使用時調出變數再進行渲染至UI。首先一樣用React當例子,來看看React對state的定義:
State 類似於 prop,但它是私有且由 component 完全控制的。
props是外部傳遞至元件內部的參數(含元件預設參數與從外部設定的變數),是無法改變的,而state是元件自己本身內部的狀態變數,是可以改變的,我們今天要看的是state。React在類別型元件設定state可以透過Class裡定義初始值後用this調用,或是透過函式型元件React Hooks的setState方法定義後從useState調用。那麼我們要怎麼在SPA裡實現類似方法呢?
再來回顧昨天實做彈出視窗的例子:
Home顯示的彈出視窗在每次切換頁面都會重複出現,如此會造成很差的使用體驗,可以想像在一般逛網站時,若每造訪一次頁面就跳出廣告,使用者有很大的機率會直接離開網站,所以正常狀況只有在第一次進入頁面會顯示彈出視窗,之後就不太會再次出現。
既然昨天我們可以在Component裡新增mount的方法執行DOM載入完成的callback,代表也可以用同樣的方式新增一個state屬性,來紀錄元件內的狀態值:
src/pages/Home.js
export const Home = {
state: {
//預設顯示狀態
show: true,
},
mount: function () {
//...
這裡可以看到在元件的state屬性賦予物件型別,為了要判斷是否已經顯示過彈出視窗,這裡在定義一個show的屬性,並給予布林值的true,代表預設情況下會顯示彈出視窗。
仔細了解state物件裡的配置:
我們剛剛已經設置好Component內的state,接下來可以看看如何使用:
export const Home = {
state: {
//預設顯示狀態
show: true,
},
mount: function () {
if (this.state.show === true) {
//呼叫modal
$('#modal').modal('show')
}
//寫入狀態
this.state.show = false
},
render: () => {
為了使用this調用全物件及子層屬性,在mount屬性裡使用function取代arrow function。首先使用if判斷show狀態是否顯示彈出視窗,若是true才會執行呼叫視窗的方法(預設值設定為true)。if判斷完畢後面統一設置show的顯示狀態為false,代表之後讀取Home頁面就不會再次彈出視窗了。
成果一覽:
順利執行,可以看到執行第一次彈出視窗後,回到Home頁面不會再次跳出視窗,不過仔細想一想,一開始在state裡定義初始值,切換頁面後state卻可以保留設定後的狀態,這是為什麼呢? 這是因為賦予state的型別為物件,利用Javascript對物件的動態操作,在state裡新增屬性與賦值,而在切換頁面時造成hashchange事件並觸發Router,Router找到對應的Component物件後,再從Component裡調用屬性,所以切換頁面不會影響state裡的狀態。那如果每次切換頁面希望state可以回復到預設值呢?其實在mount裡對state重新進行設定就好啦!以上是今天的內容,我們明天見!
參考資料:
[React學習筆記] 暸解狀態 state 與 setState