การสร้าง UI ด้วย React (III) - การเขียน JSX
Published: 2024-02-27 08:48:06

_JSX_ เป็นส่วนขยายของ **JavaScript** ที่ ทำให้เราเขียนภาษา Markup แบบเดียวกับ HTML ในไฟล์ JavaScript ได้

---

ในซีรีย์นี้:
- [การสร้าง React Component](https://dev.to/21aki/kaarsraang-ui-dwy-react-i-kaarsraang-react-component-29no)
- [Import และ Export Component](https://dev.to/21aki/kaarsraang-ui-dwy-react-ii-import-aela-export-component-pge)
- **เขียน JSX**
- [ใช้ ปีกกา ใน JSX](https://dev.to/21aki/kaarsraang-ui-dwy-react-iv-aichpiikkaaain-jsx-3793)
- ส่งค่าผ่าน Props
- การแสดง Component แบบมีเงื่อนไข (Conditional Rendering)
- การแสดงข้อมูลเป็น List
- แยก Component (สร้าง Pure Component)
- มอง UI ให้เป็นแผนภูมิต้นไม้ (Tree Structure)

---
### JSX: HTML เวอร์ชั่น JavaScript 

ปกติหากเราพัฒนาเว็บ เราจะเขียน HTML, CSS และ JavaScript แยกไฟล์เป็นส่วนๆ:

![HTML JavaScript](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/99qooc47x33p7vj01quv.png)

แต่ใน React เราสามารถรวมทั้งหมด เพื่อ Render พร้อมๆ กันได้ใน Components:

![JSX](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d711izg74yjb7x2aiaed.png)

เมื่อเป็นแบบนี้ เราสามารถแยกส่วนแต่ละ UI ให้โค้ดแยกกันได้ เช่น โค้ดทั้งหมดของปุ่ม จะถูกแยกจาก โค้ดทั้งหมดของ sidebar อย่างชัดเจน

ในแต่ละ React Component จะเป็นฟังค์ชั่น JavaScript ที่รวม JSX ซึ่งเป็น HTML เวอร์ชั่น JavaScript วิธีที่จะเข้าใจ JSX ง่ายที่สุดคือลองแปลง HTML ไปเป็น JSX

> **📝 ข้อสังเกตุ**
> JSX กับ React เป็นคนละอย่างกัน แต่มักถูกใช้ร่วมกัน, เราสามารถเลือกใช้อย่างใดอย่างหนึ่งได้. JSX เป็นส่วนขยายสำหรับการเขียนโปรแกรม, ส่วน React เป็น library ในภาษษ JavaScript.

### แปลง HTML ไปเป็น JSX

จากตัวอย่าง ภาษา HTML:

```html
<h1>Hedy Lamarr's Todos</h1>
<img 
  src="https://i.imgur.com/yXOvdOSs.jpg" 
  alt="Hedy Lamarr" 
  class="photo"
>
<ul>
    <li>Invent new traffic lights
    <li>Rehearse a movie scene
    <li>Improve the spectrum technology
</ul>
```

เราต้องการนำมาใส่ใน Component นี้:

```jsx
export default function TodoList() {
  return (
    // ???
  )
}
```

หากเราก้อป แปะ ไปตรงๆ โค้ดจะใช้ไม่ได้

{% codesandbox 9m6zmf %}

เพราะ JSX มีกฎเพิ่มเติมจาก HTML หากเราอ่านข้อความ error ด้านบน ก็จะบอกใบ้เราแล้วว่าจะต้องแก้ยังไง

> **📝 ข้อสังเกตุ**
> เมื่อเรารัน React แล้วเกิดข้อความ error บนหน้าจอ จะช่วยเราหาว่าปัญหาอยู่ตรงไหน หากติดก็ให้อ่านข้อความ error ดูดีๆ

### กฎของ JSX 

#### 1. ต้อง return ออกมาเป็น Element เดียว

หากเราต้องการแสดง Element หลายๆ Element พร้อมๆ กัน ให้เราคลุมด้วย Tag สัก Tag เพื่อให้มันออกมาชั้นนอกสุดเพียง Element เดียว เช่นตัวอย่างนี้ใช้ `<div>` ครอบ

```jsx
<div>
  <h1>Hedy Lamarr's Todos</h1>
  <img 
    src="https://i.imgur.com/yXOvdOSs.jpg" 
    alt="Hedy Lamarr" 
    class="photo"
  >
  <ul>
    ...
  </ul>
</div>
```

หรือเราสามารถครอบด้วย `<>` และ `</>` แทน `<div>` ก็ได้:

```jsx
<>
  <h1>Hedy Lamarr's Todos</h1>
  <img 
    src="https://i.imgur.com/yXOvdOSs.jpg" 
    alt="Hedy Lamarr" 
    class="photo"
  >
  <ul>
    ...
  </ul>
</>
```

Tag ที่ว่างๆ นี้ (`<>` และ `</>`) เราจะเรียกว่า _**Fragments**_

#### 2. ปิดทุก Tags

ใน JSX จะต้องมีการปิด Tag ทั้งหมด, หากเป็น Tag เดี่ยวๆ เช่น `<img>` ต้องเปลี่ยนเป็น `<img />` และ Tag ที่มีการเปิดและปิดอย่าง `<li>oranges` จะต้องเขียนปิด Tag เป็น `<li>oranges</li>` เสมอ ดังตัวอย่าง:.

```jsx
<>
  <img 
    src="https://i.imgur.com/yXOvdOSs.jpg" 
    alt="Hedy Lamarr" 
    class="photo"
   />
  <ul>
    <li>Invent new traffic lights</li>
    <li>Rehearse a movie scene</li>
    <li>Improve the spectrum technology</li>
  </ul>
</>
```

#### 3. ใช้ camelCase กับ~~ทั้งหมด~~เกือบทุกอย่าง

JSX จะถูกแปลงเป็น JavaScript และ attribute ของ Tag HTML จะถูกแปลงเป็น Key ของ object ใน JavaScript และใช้ attribute เหล่านั้นเป็นตัวแปร แต่ด้วยข้อจำกัดในการตั้งชื่อตัวแปรของ JavaScript เราจะไม่สามารถตั้งชื่อที่มีขีด หรือใช้คำสงวนอย่าง `class` ได้

ด้วยเหตุนี้ ทำให้ใน React, attribute ของ HTML และ SVG จะถูกเขียนเป็น camelCase  เช่น `stroke-width` จะต้องเขียนเป็น `strokeWidth` และเนื่องจาก `class` เป็นคำสงวน ใน React จะถูกเปลี่ยนเป็น `className` แทน[ตามชื่อใน DOM](https://developer.mozilla.org/en-US/docs/Web/API/Element/className):

```jsx
<img 
  src="https://i.imgur.com/yXOvdOSs.jpg" 
  alt="Hedy Lamarr" 
  className="photo"
/>
```

### Pro-tip: ใช้ตัวแปลง JSX

เราสามารถเอา HTML หรือ JSX ไปแปลงผ่าน[ตัวแปลง](https://transform.tools/html-to-jsx)ได้ 

เมื่อแปลง HTML เป็น JSX แล้ว จะได้ผลลัพท์ดังนี้ :

{% codesandbox j9tr6f %}

### สรุป
- Components ใน React จะถูก render พร้อมกับเงื่อนไขต่างๆ กับ JSX.
- JSX คล้ายคลึงกับ HTML, โดยมีข้อแตกต่างเล็กน้อย. โดยแปลงได้โดยใช้[ตัวแปลง](https://transform.tools/html-to-jsx)ได้ .
- หากพบปัญหา ให้ดูข้อความ Error จะช่วยแนะนำแนวทางแก้ไข JSX ให้ถูกต้องได้.