3-4 React 中表單的基本應用
本單元對應的專案分支為:convert-internet-speed。
雖然現在畫面上的圖示還沒辦法正常顯示,但在這個單元中,我們會先來了解如何在 React 中取得使用者在表單所輸入的資料。本單元完成後,使用者可以透過在左邊的 input 欄位輸入 Mbps 的數值後,直接在右邊得到轉換後的 MB/s,如下圖所示:

使用 input 提供使用者輸入資料的地方#
首先要能夠將 Mbps 轉換成 MB/s 之前, ㄧ定需要先知道使用者輸入了什麼內容,因此在網速單位轉換器中,在 .converter 區塊內有 <input /> 標籤是要讓使用者輸入的:

在 input 元素上綁定 onChange 事件#
和之前學到綁定點擊事件的方式相同,若要監控使用者在 <input /> 欄位中輸入了什麼,可以使用 onChange 事件,可以在 <input /> 內加上 onChange,在後面的 {} 內透過 console.log 來看看是否會觸發此事件,像是這樣:
現在當使用者在左側的對話框中輸入數字時,應該就可以在瀏覽器的 console 視窗中看到一直會跳出 onChange 的訊息。
透過 useState 讓 React 明白資料的變化#
現在雖然在使用者輸入對話框的訊息時,會觸發 onChange 事件,但和上一章中曾提過的一樣,只是監聽事件 React 並沒辦法得知它內部是否有任何資料改變,因此也不會知道是不是需要重新轉譯畫面。
為了要讓使用者在輸入左側的 Mbps 時,右側 MB/s 在畫面上的值能夠連動改變,因此需要把使用者輸入的內容透過 state 紀錄在 React 元件中,一但 React 發現這個 state 的內容有改變時,就會重新轉譯畫面。要在 React 元件中紀錄資料,就會用上一章使用過 useState 這個 React Hooks。
步驟一:載入 useState 方法#
和上一章中可以載入 useState 的方法不同,因為上一章是直接使用 CDN 載入 React 套件,這裡我們是把 React 套件下載到本機電腦上,因此要使用 React 或其內部的 useState 方法的話,都需要透過 import 的方式:
步驟二:使用 useState 方法#
還記得 useState() 這個 React Hooks 的使用方式嗎?這個方法可以帶入參數當作預設值,呼叫之後會回傳兩個值,其中一個是 state,另一個是用來改變 state 的方法,因此在這裡我們可以把預設值設為 0,並取得 inputValue 和 setInputValue 這兩個回傳值:
步驟三:定義 onChange 的事件處理器#
在上個章節實作計數器的時候,我們是定義使用者點擊按鈕後的事件處理器,這裡則是要定義使用者輸入內容時的事件處理器,也就是要把使用者輸入的內容先透過 e.target.value 的方式取出來,然後透過 setInputValue 這個方法,請 React 幫我們更新 inputValue 這個 state 的資料。如此,當使用者輸入的資料有變更時,React 就能夠馬上知道:
:: tip
在 React 中,常使用 handle 當作事件處理器命名的開頭,例如 onClick 對應到 handleClick,onChange 對應到 handleChange。
:::
步驟四:把 onChange 事件換成寫好的事件處理器#
最後,只需要把剛剛在 input 上寫的 onChange 事件改成這裡寫好的事件處理器即可。另外,要留意的地方是,這裡的 input 元素中,需要把 inputValue 這個 state 帶到 <input> 的 value 屬性中,像是這樣:
步驟五:讓畫面右邊的 input 值也同步更新#
在還沒有實作單位換算的功能之前,我們先讓右側的 input 欄位直接顯示使用者輸入的內容,如果能夠正常顯示的話,最後我們只需要做簡單的數學換算就可以了:
現在當使用者在左側輸入內容時,右側的數值就會跟著同步變動。
步驟六:加上單位換算的功能#
最後我們只需要加上單位換算的功能就完成了,在前面的單元中我們有提到 1 Mbps = 0.125 MB/s ,也就是 Mbps 的值除以 8 才會是 MB/s:

因此,要正確的單位轉換,只需要修改右側帶入 <input /> 中的 value,讓它是使用者輸入的值除以 8 即可,也就是 value={inputValue/8}:
了解畫面更新的邏輯#
現在當使用者在左側輸入內容時(Mbps),右側就會馬上顯示換算好的網速(MB/s)。先前我們有提到,在 React 中是透過資料變動來驅動畫面更新,讓我們用同樣的觀念來思考一下這裡畫面是如何更新的。
使用者之所以能夠在畫面的右側看到自己輸入的內容,是因為下面這一連串過程導致畫面重新轉譯後,才把最新的 inputValue 顯示在使用者的畫面上:

換你了:完成網速單位換算的功能#
現在要請你試著參考上面的步驟與說明,試著完成網速單位換算的功能,讓使用者在左側 Mbps 的欄位中輸入資料時,右側就會即時顯示對應 MB/s 的值,主要過程會包含:
- 使用
useState建立 React 狀態(state) - 定義
handleInputChange事件,當使用者輸入內容時能夠更新資料狀態 - 將
handleInputChange透過onChange和 input 進行綁定 - 在畫面左側 input 欄位中透過
value欄位以更新資料 - 在畫面右側 input 欄位中透過
value / 8的欄位以達到單位換算
畫面將會像這樣:

現在網速單位換算的功能已經完成了,但接下來會先說明 React 中元件拆分和資料間傳遞的重要觀念,最後才來透過元件的方式,讓圖示能夠正確呈現在畫面。
本單元相關之網頁連結、完整程式碼與程式碼變更部分可於 convert-internet-speed 分支檢視,在這個單元中我們僅修改了 ./src/App.js 這支檔案,如果實作上有碰到任何問題的話,都可以到下面的連結檢視完整的程式碼:
