1. 程式人生 > >深入理解 Props 和 State

深入理解 Props 和 State

系列部落格: 用通俗的語言和塗鴉來解釋 React 術語

上篇文章中,我們介紹了元件、props 和 state 。

props 和 state 的區別相當明顯,確定何時使用 props 和 state 似乎也很簡單。舉個例子,屋頂的顏色自然就是 prop ,因為顏色是屋頂的固有屬性。另一方面,門的開關狀態很顯然是 state ,因為門在建立後還可以開啟或關上。然而在本文中,我們將來挑戰這一思維方式!

沒開玩笑?!?沒錯,你所看到的東西既可以是 prop,又可以是 state 。並沒有絕對的界限。我將介紹一種更有用、偏實戰的方式來思考 prop 和 state 。

學習目標

當你讀完本文後希望你能重新回到這裡,並能夠輕鬆回答以下問題:

  • props 和 state 的主要用途是什麼?
  • “state 提升”的含義是什麼?在什麼場景下需要提升 state ?

新成員

你注意到房子周圍的新成員了嗎?試試點選房門!

這是一隻嗜睡的貓,門一關她就睡,只有當門再開啟的時候才會起來。如果把門關上,她立即又睡過去了。

實現貓

現在我來問你,如果實現貓的行為?先來試試吧!

先從下面的“程式碼”入手,花點時間先讀一遍。(再次重申,這並非真正的 JavaScript 程式碼,它只是以一種簡化的形式來幫助你理解概念,同時不會被 JS 中的細節所幹擾。)

JavaScript
1234567891011121314151617 House:<div><Roof/><Wall/><Window/><Door/><Cat/></div>Door:State:status<!--"open""closed"--><div>{state.status}door</div>當點選門時如果door.state.status"open"door.state.status修改成"closed"
否則將door.state.status修改成"open"

House 元件中又新增了 Cat 標籤。那麼 Cat 元件又是怎麼樣的呢?我們來定義它。

貓要麼睡、要麼醒。這似乎跟門的開關狀態很類似。或許我們同樣可以使用 state 來表示貓的狀態:

JavaScript
123 Cat:State:status<!--"sleeping""awake"--><div>{state.status}cat</div>

Cat 元件定義好後,還需要實現的就只剩下將貓和門的狀態進行同步。門的狀態為 “open” 時,我們想要貓的狀態為 “awake”,反之為 “sleeping” 。

就這麼簡單?看看再說吧…

第一次嘗試

既然我們已經有了根據當前狀態切換門狀態的程式碼,莫不如我們就在此處切換貓的狀態:

JavaScript
12345678910 Door:State:status<!--"open""closed"--><div>{state.status}door</div>當點選門時如果state.status"open"state.status修改成"closed"cat.state.status修改成"sleeping"<!--錯誤的-->否則將state.status修改成"open"cat.state.status修改成"awake"<!--錯誤的-->

不幸的是,這不起作用!還記得元件的 state 是私有資料嗎?只有在元件的內部才能訪問。其他元件,無論是父元件還是兄弟元件,都無法訪問本元件的 state 。

很遺憾,我們在 Door 元件內嘗試修改貓的狀態以失敗告終。(轉換成真正的 JavaScript 程式碼也不例外)

第二次嘗試

那麼在 Cat 元件內來修改貓的狀態如何?這次應該可以的,是吧?

JavaScript
12345678 Cat:State:status<!--"sleeping""awake"--><div>{state.status}cat</div>當點選門時<!--黑人門號臉???怎麼個點選法?-->如果door.state.status"open"<!--錯誤的-->cat.state.status修改成"sleeping"否則將cat.state.status修改成"awake"

毫無疑問,在 Cat 元件內修改貓的狀態是沒問題的。但我們需要讀取門的狀態來決定貓的狀態是什麼。門的狀態是 Door 元件的 state ,因此無法在 Cat 元件裡訪問!

解決辦法

呃!太蹩腳了。要保持門和貓的狀態同步,我們必須要在某處能同時訪問兩者。但看上去資料是通過設計而對外隱藏的。如果來解決此難題呢?

解決辦法就是需要我們靈活地理解 state 和 props 的用法。

提升門的 state

House 元件:

JavaScript
123456 House:<div>...<Door/><Cat/></div>

DoorCat 是並排放置的。或許這就是可以輕鬆同步它們的地方?

但是,我們現在是在 House 元件內。與之前的嘗試同理,在這裡是沒辦法讀取 Door 的 state 或者改變 Cat 的 state 。

但如果我們使用 props 來替代 state 呢?

JavaScript
123456 House:<div>...<Door status="open"/><Cat status="awake"/></div>

當門關上時:

JavaScript
123456 House:<div>...<Door status="closed"/><Cat status="sleeping"/></div>

當然,門的狀態不會是固定的值,它會隨時間而改變。我們用 doorStatus 來表示門的狀態。

JavaScript
123456 House:<div>...<Door status={doorStatus}/><Cat status={如果doorStatus'open'值為'awake'否則為'sleeping'}/></div>

這不就解決同步的問題了嘛。順便問下,這個會變化的值 doorStatus 是什麼?在元件中什麼是可以改變的?沒錯,正是 state 。

JavaScript
1234567 House:State:doorStatus<!--'open''closed'--><div>...<Door status={state.doorStatus}/><Cat status={如果state.doorStatus'open'值為'awake'否則為'sleeping'}/></div>

太棒了!House 元件現在定義的很好,門和貓的狀態也能完美同步。

我們還需要修改 DoorCat 元件,使用 props 來代替 state :

JavaScript
1234 Door:<div>{props.status}door</div>Cat:<div>{props.status}cat</div>

正如你所見,因為我們想要使用來父元件的 state,在這種情況下,為了設定貓的狀態,門的狀態其實是來自於 House 的,我們可以將相同的資料表示為父元件的 state,並將資料作為 props 傳遞給子元件。通常,這被稱之為 state 提升。我們將 state 移至元件的更高層級處。

更改房子的 state

現在門和貓的狀態通過房子的 state 進行連線。如果想開門或喚醒貓的話,我們需要更改 House 元件的 state 。

問題來了,哪裡是唯一可以更新 House 的 state 的地方?就在 House 元件內,沒錯吧?

但是,我們想要在 Door 裡來觸發這次更改。也就是說,我們想要的效果是隻有當點選門時才開門,而不是點選整個房子或窗戶等。

所以 Door 元件需要做些改動:

JavaScript
1234 Door:<div>{props.status}door</div>當點選門時做某件事來修改`House`state

但等等,之前不是說不能在 Door 元件內修改 House 的 state 嗎?

沒錯。我們沒辦法直接修改 House 的 state 。但並不等於說不能間接地修改。看下面…

House 元件內,我們來寫程式碼以實際修改它的 state :

JavaScript
12345678 House:State:doorStatus<!--'open''closed'-->toggleDoorStatus:如果state.doorStatus'open'state.doorStatus修改成'closed'否則將state.doorStatus修改成'open'...

此刻,我們還未指定何時執行這段程式碼。我們只是給了它一個名字 (toggleDoorStatus),以便稍後通過名稱來找到它執行。

然後將 toggleDoorStatus 作為 prop 傳遞給 Door 元件:

JavaScript
1234567 House:...<div>...<Door...onClickAction={toggleDoorStatus}/>...</div>

Door 元件中,我們只需執行這個點選操作即可:

JavaScript
1234 Door:<div>{props.status}door</div>當點選門時執行props.onClickAction<!--實際執行的是名為"toggleDoorStatus"的程式碼-->

這就像把電視遙控器傳遞給其他人一樣。某人在 Door 元件內按下了遙控器按鍵。House 元件裡的電視機就會換臺或加大音量。

將會發生什麼取決於傳給 Door 的遙控器是什麼。它可能控制的是房間裡的電視、空調或高保真音響系統。在 Door 元件內,某人需要做的只是按下遙控器的按鍵。

這就是我們所需要的!下面是完整“程式碼”:

JavaScript
12345678910111213141516

相關推薦

深入理解 Props State

系列部落格: 用通俗的語言和塗鴉來解釋 React 術語 在上篇文章中,我們介紹了元件、props 和 state 。 props 和 state 的區別相當明顯,確定何時使用 props 和 state 似乎也很簡單。舉個例子,屋頂的顏色自然就是 prop ,因為顏色是屋頂

深入解析React propsstate屬性

本文主要介紹了React props和state屬性的具體使用方法,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧 props 不知道大家還記不記得xml標籤中的屬性,就像這樣: <class id="1"> <studen

OpenStack實踐系列⑦深入理解neutron虛擬機

ice 賬號 由器 1.0 鏡像 多租戶 ridge 不同的 img OpenStack實踐系列⑦深入理解neutron和虛擬機 五、深入理解Neutron 5.1 虛擬機網卡和網橋 [[email protected]/* */ ~]# ifconfig

深入理解cookiesession

上一個 action inpu 用戶 character method 角色 默認 image cookie和session在java web開發中扮演了十分重要的作用,本篇文章對其中的重要知識點做一些探究和總結。(轉發自https://www.cnblogs.com/ro

c#基礎系列3---深入理解ref out

ref 聲明 函數的參數 .... -- 新增 tel struct 結果 “大菜”:源於自己剛踏入猿途混沌時起,自我感覺不是一般的菜,因而得名“大菜”,於自身共勉。 擴展閱讀 c#基礎系列1---深入理解 值類型和引用類型 c#基礎系列2---深入理解 Str

深入理解i++++i的區別

首先: i++ : 先取i的值作為表示式的值,然後執行 i = i + 1 ++i : 先執行 i = i + 1,再取運算完之後的值作為表示式的值 舉例和解釋: 先來個熱身的簡單例子 public static void main(String[] args

react and redux(一)propsstate

安裝 示例 總結 安裝 安裝好node.js和npm之後,命令列執行下面的命令: npm install --global create-react-app 建立應用目錄: create-react-app fi

【半轉載】深入理解getpost的區別一些思考

前言 PHP有道很經典的面試題,請回答get和post的區別,在網上找了很多答案,看到了很多有意思的想法,現在我們一起由淺入深的探討一下~ 下面這個表格是某個講學視訊筆記的講解:   get post

React propsstate屬性的具體使用方法

本篇文章主要介紹了React props和state屬性的具體使用方法,具有一定的參考價值,對此有需要的朋友可以參考學習下。如有不足之處,歡迎批評指正。 props 不知道大家還記不記得xml標籤中的屬性,就像這樣: <class id="1"> <studen

React中propsstate相同點不同點

朋友們,我想死你們了,最近這幾天忙著和病魔作鬥爭所以沒怎麼寫部落格,今天感覺好點了,趕緊來寫一波,就是這木敬業。 今天我們來討論討論props和state相同點和不同點 首先我來概要說明一下這兩者 props:   props是一個從外部傳進元件的引數,由於React具有單向資料流的特性,所以他的主要

React props state

props props 獲取的是外部傳入的值在元件中只能使用不能修改 物件作為屬性值 var obj = { name1:"deft", name2:"iboy" } // ... 這是一個語法糖 延遲操作符 ReactDOM.render

【web基礎】深入理解httphttps的區別

在對比這兩者的區別之前咱們先來看一下http有哪些缺點 第一個缺點:http通訊使用明文可能會被竊聽。由於http本身不具備加密的功能,所以也無法做到對通訊整體(使用http協議通訊的請求和響應)的加密。也就是說http的報文使用的是明文傳送。 為什麼通訊不加密

第十五節:深入理解asyncawait的作用及各種適用場景用法

一. 同步VS非同步 1.   同步 VS 非同步 VS 多執行緒 同步方法:呼叫時需要等待返回結果,才可以繼續往下執行業務 非同步方法:呼叫時無須等待返回結果,可以繼續往下執行業務 開啟新執行緒:在主執行緒之外開啟一個新的執行緒去執行業務 同步方法和非

react~propsstate的介紹與使用

props是引數的傳遞,從上層模組向下層模組進行拿傳遞;而state是提局域變數,一般在本模組內使用,props是不能改變的,而state可以通過setState去修改自身的值。 props React的核心思想就是元件化思想,頁面會被切分成一些獨立的、可複用的元件。 元件從概念上看就是一個函式,可以接受

深入理解 hashcode() HashMap 中的hash 演算法

前言 Java中的HashMap非常常用也非常重要, 提到HashMap是離不開hashcode()方法的, 整天嘴邊掛著HashMap、Hashtable、TreeMap、LinkedHashMap、IdentityHashMap、ConcurrentHashMap和WeakHashMap等詞

深入理解ob_flushflush的區別

ob_flush/flush在手冊中的描述, 都是重新整理輸出緩衝區, 並且還需要配套使用, 所以會導致很多人迷惑… 其實, 他們倆的操作物件不同, 有些情況下, flush根本不做什麼事情.. ob_*系列函式, 是操作PHP本身的輸出緩衝區. 所以, ob_flus

React Native基礎&入門教程:以一個To Do List小例子,看propsstate

本文由葡萄城技術團隊於部落格園原創並首發 轉載請註明出處:葡萄城官網,葡萄城為開發者提供專業的開發工具、解決方案和服務,賦能開發者。 在上篇中,我們介紹了什麼是Flexbox佈局,以及如何使用Flexbox佈局。還沒有看過的小夥伴歡迎回到文章列表點選檢視之前的文章瞭解。 那麼,當我們有了基本

Django第八篇,深入理解檢視url

目錄  URL 配置小技巧  簡化匯入函式的方式  在除錯模式下提供特殊的 URL  具名分組 示例請求:  捕獲的引數始終是字串 為檢視的引數指定預設值 錯誤處理  引入其他 URL 配置 捕獲的引

深入理解“靜態”static關鍵字

「深入理解」系列,本文介紹“靜態”的概念、在記憶體中的分佈和應用 關於“靜態”的誤解:重新認識static關鍵字 靜態(static)這個詞,翻譯過來就是“靜態的、靜止的”,至於為什麼叫