iT邦幫忙

2023 iThome 鐵人賽

DAY 25
0
Modern Web

30 days of React 系列 第 25

Day 25 - React 基礎實作練習:下拉式選單

  • 分享至 

  • xImage
  •  

今天要來練習做下拉式選單選擇國家。目前我們的程式碼已經有基礎的樣式。需要讓下拉式選單的功能正常運作。

  • 目前有的程式碼:
import React from "react";

import { COUNTRIES } from "./data";
const countriesNames = Object.entries(COUNTRIES);

function App() {
  const [country, setCountry] = React.useState("");

  return (
    <form>
      <fieldset>
        <legend>Shipping Info</legend>
        <label htmlFor="country">Country:</label>
        <select
          required
          id="country"
          name="country"
          value={country}
          onChange={(event) => {
            setCountry(event.target.value);
          }}>
          <option value="">- Select Country -</option>
          <optgroup label="Countries">
            {countriesNames.map(([id, label]) => {
              return (
                <option key={id} value={id}>
                  {label}
                </option>
              );
            })}
          </optgroup>
        </select>
      </fieldset>

      <p className="country-display">Selected country: {COUNTRIES[country]}</p>

      <button>Submit</button>
    </form>
  );
}

export default App;

畫面是這樣子:

  • 國家資料程式碼:
export const COUNTRIES = {
  AF: "Afghanistan",
  AL: "Albania",
  DZ: "Algeria",
  AS: "American Samoa",
  //...
};

操作步驟

Step 1:取得國家的資料。

const countriesNames = Object.entries(COUNTRIES);
//const countriesNames = Object.keys(COUNTRIES);//可以取得國碼
//const countriesNames = Object.values(COUNTRIES);//可以取得值

Step 2:遍歷國家資料

在 return 的 JSX 當中,使用解構賦值的寫法來分別區分國家碼和國家名稱。

{
  countriesNames.map(([id, label]) => {
    return <option>{label}</option>;
  });
}

在這個步驟,已經初步完成了讓選單內出現了所需要的國家清單。

Step 3:設定 JSX 的 attributes

接著要來處理 state 的部分,可以使用國家的代碼來設定 key 和 value。

  <option key={id} value={id}>

Step 4:設定事件

在 select 標籤上設定onChange event prop

     <select
          id="country"
          name="country"
          onChange={event=>{
            console.log(event.target)
          }}
        >

在目前event.target 改變觸發的是 HTML element

更進一步改成event.target.value的話,console.log 的結果則會是國家的代碼。

會有這樣的結果是因為在第三步驟時我們將select

value設定為{id} 了。現在當我們選擇該國家

「Selected country」就會顯示該國家相應的代碼。

完成這個步驟看似一切都已經就定位了,真的有需要設定value嗎?假設不設定 select 標籤的value 屬性好了,當我們將初始值設定為

const [country, setCountry] = React.useState("BZ");

按照邏輯應該要是「Brazil」巴西才對,但結果卻是以下的樣子:

也就是說這樣子的資料流是單向的。可以透過 select 的事件變化來觸發渲染,但卻沒辦法透過 state 來設定初始值。所以value的設定是必要的,這也是資料綁定(Data-Binding)的概念。所以在這個步驟,我們也應該在 select 標籤上面設定value

value = { country };

這邊的 country 也就是在useState 當中的初始值。

Step 5:確保資料綁定

接著要來處理預設的畫面,也就是使用者尚未點擊之前,選單需顯示「-Select Your Country-」。可以透過追加一個 option 元素來達成,

<option>-Select Your Country-</option>

這樣子已經有了初始的選項,我們可以追加一些細節讓它更加完善,在 option 元素中添加一個value 的屬性值設定為 empty

並且在 select 元素上設定required 來讓選項設定為必填。這樣使用者如果直接送出表單,那麼便會跳出「Please select an item in the list.」的通知。

<option value="">- Select Country -</option>

Step 6:分類選項

再來可以再稍微調整一下使用者體驗的部分,可以使用optgroup 這個標籤來把國家區分開來。

<optgroup> 是 HTML 中的一個標籤,用於在 <select> 元素中組織和分類選項。當你有一個包含多個選項的下拉列表時,有時候希望這些選項被分組顯示,以增加可讀性和組織性。

<optgroup>可以編輯 label 標籤:

          <option value="">
            - Select Country -
          </option>
          <optgroup label="Countries">
            {countriesNames.map(
              ([id, label]) => {
                return (
                  <option
                    key={id}
                    value={id}
                  >
                    {label}
                  </option>
                );
              }
            )}
          </optgroup>

像這樣把「-Select Country -」和國家列表區隔開來,便可達到這樣子的效果,可以看到灰底的「Countries」區隔了「-Select Country -」和國家清單。

Step 7:調整所選國家顯示

最後一步,黃色的區塊,目前顯示的是所選國家的代碼,這邊若要讓它顯示為所選國家,可以改成以下這樣子:

<p className="country-display">Selected country: {COUNTRIES[country]}</p>


這樣即完成國家列表的下拉式選單了。

以上是今天的練習。

參考資料

  • The Joy of React by Josh W Comeau - form (exercises)

上一篇
Day 24 - React 基礎實作練習:輸入授權碼
下一篇
Day 26 - React 基礎實作練習:追加購物清單
系列文
30 days of React 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言