JSX Component

Component ส่วนประกอบของหน้าเว็บเรา ว่าจะส่วนไหน เมนู ส่วนแสดงผลหลัก เป็นต้น โดยตัว Component รับ Input อะไรก็ได้ Text / Number หรือ แม้แต่ตัว Component เอง แต่เจ้า jsx return ได้ 1 element เท่านั้น

  • แบบ Error
const HelloWorld = ({name = "PingkungA"}) => {
  return <h3>Hello {name}</h3>
         <h3> World !!!!</h3>
}
  • แบบที่แก้แล้ว ต้องเอา Tag มาหุ้ม อันนี้เอา <div> มาหุ้ม
const HelloWorld = ({name = "PingkungA"}) => {
  return {
     <div>
       <h3>Hello {name}</h3>
       <h3> World !!!!</h3>
     </div>
  }
}

Create Component with props

  • property (props)
  • validation rule
- Sample
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
import PropTypes from 'prop-types';

const HelloWorld = (props) => {
  return <h3>Hello {props.name}</h3>
}

HelloWorld.propTypes = {
  name: PropTypes.string.isRequired
};

function App() {

  return (
    <div className="App">   
      <h2> Call Component with out pass paramater</h2>
      <HelloWorld/>
      <br/> 

      <h2> Call Component with paramater</h2>
      <HelloWorld name="React" />
      <br/> 

      <h2> Call Component with paramater empty string</h2>
      <HelloWorld name="" />
      <br/> 

      <h2> Call Component with paramater undefined</h2>
      <HelloWorld name={undefined}/>
    </div>
  )
}

export default App
- Result

ถ้าส่ง Undefine ผ่าน มันถือว่าส่ง แต่อันแรกไม่รอด โดย Validation ดัก เดี๋ยวมีอธิบายตอนท้ายในหัวข้อ Component Validation

Create Component without props

แก้ในส่วนของ Component จาก Props มาใช้พวก Object Destructuring 

  • ของเดิม - {props.name}
  • ของใหม่ - เรียก {name} แถมยังกำหนด Default Parameter ให้ด้วย เคสนี้ผมกำหนดเป็น PingkungA

ตัว Object Destructuring จริงมากับตัว ES6 อยู่แล้ว เท่าที่ลองใช้ มันอ่าน Code สะดวกขึ้นนะ

- Sample
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
import PropTypes from 'prop-types';

const HelloWorld = ({name = "PingkungA"}) => {
  return <h3>Hello {name}</h3>
}

HelloWorld.propTypes = {
  name: PropTypes.string.isRequired
};

function App() {

  return (
    <div className="App">    

      <h2> Call Component with out pass paramater</h2>
      <HelloWorld/>
      <br/> 

      <h2> Call Component with paramater</h2>
      <HelloWorld name="React" />
      <br/> 

      <h2> Call Component with paramater empty string</h2>
      <HelloWorld name="" />
      <br/> 

      <h2> Call Component with paramater undefined</h2>
      <HelloWorld name={undefined}/>
    </div>
  )
}

export default App
- Result

เหมือนกับแบบแรกเลยครับ เปลี่ยนไปแล้ว ยังทำงานได้อยู่

Component Validation

จากที่ผ่านมา มันจะมีตัว Input ส่งเข้าไปในแต่ละ Component แต่เราจะรู้ได้อย่างไร ว่ามันสำคัญ หรือ ไม่สำคัญหละ ? ตัว JS เองมีตัวช่วย จริงตอนผมลอง ES6 Lint มันบังคับ 555 ได้แก่

- propTypes

ในตัวอย่างตอนต้นใส่ไปแล้ว มาดูอีกตัวอย่างอธิบายให้ชัดขึ้น ตอนนี้ผมมีสร้าง Component อีกดตัวชื่อ SelfIntroduction รับตัวแปร

  • name : string และ required
  • age : number
  • address : string

เราสามารถกำหนด SelfIntroduction.propTypes ตามด้านล่างเลย

const SelfIntroduction = ({name = "PingkungA", age, address}) => {
  return (
    <div>
      <h3>My name is {name}</h3>
      {/* Conditional formatting by using short if (TERNARY operator) */}
      {age ? <h3>I&apos;m {age} years old</h3> : null}
      {age && <h3>I&apos;m {age} years old</h3>}
      {name || age }
      {/* Conditional formatting by using if */}
      {
        (() => {
          console.log(address)
          if (address) {
            return (
              <h3>I live in {address}</h3>
            )
          }
        })()
      }
    </div>
  )
}

SelfIntroduction.propTypes = {
  name: PropTypes.string.isRequired,
  age: PropTypes.number,
  address: PropTypes.string
};
- TypeScript
  • เพิ่ม // @ts-check ที่หัวไฟล์
  • fixed import ให้เรียบร้อย เดี๋ยว VS Code มันจะ Hint ให้
  • ที่ Component กำหนด jsdoc มาเพิ่มของ Self Introduction ดังนี้
/**
 * 
 * @type {React.FC<{name: string}>}
 *
 * @returns {React.ReactNode}
 */
  • Code ตอนจะประมาณนี้
// @ts-check
import React, { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
import PropTypes from 'prop-types';

/**
 * 
 * @type {React.FC<{name: string}>}
 *
 * @returns {React.ReactNode}
 */
const SelfIntroduction = ({name = "PingkungA", age, address}) => {
  return (
    <div>
      <h3>My name is {name}</h3>
      {/* Conditional formatting by using short if (TERNARY operator) */}
      {age ? <h3>I&apos;m {age} years old</h3> : null}
      {age && <h3>I&apos;m {age} years old</h3>}
      {name || age }
      {/* Conditional formatting by using if */}
      {
        (() => {
          console.log(address)
          if (address) {
            return (
              <h3>I live in {address}</h3>
            )
          }
        })()
      }
    </div>
  )
}

function App() {

  return (
    <div className="App"> 
      <SelfIntroduction name="PingkungA" age={33}/>
    </div>
  )
}

export default App
  • หลังจากเพิ่มเสร็จ มันจะบอก Error ตัวแดงๆเลย เคสนี้ผมเพิ่มเฉพาะ name ตัวแปรอื่นๆ โดยมันฟ้อง
  • ถ้าเราแวะกลับไปดูที่ Component 2 ตัวนี้ Error เหมือนกัน
  • กลับมาเติมให้ครบ jsdoc ทั้ง age / address 2 ตัวหลังไม่ Required ใส่ ? ต่อท้าย
// @ts-check
import React, { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
import PropTypes from 'prop-types';

/**
 * 
 * @type {React.FC<{name: string, age?: number, address?: string}>}
 *
 * @returns {React.ReactNode}
 */
const SelfIntroduction = ({name = "PingkungA", age, address}) => {
  return (
    <div>
      <h3>My name is {name}</h3>
      {/* Conditional formatting by using short if (TERNARY operator) */}
      {age ? <h3>I&apos;m {age} years old</h3> : null}
      {age && <h3>I&apos;m {age} years old</h3>}
      {name || age }
      {/* Conditional formatting by using if */}
      {
        (() => {
          console.log(address)
          if (address) {
            return (
              <h3>I live in {address}</h3>
            )
          }
        })()
      }
    </div>
  )
}

function App() {

  return (
    <div className="App"> 
      <SelfIntroduction name="PingkungA" age={33}/>
    </div>
  )
}

export default App
  • รวมถึง hint ตอนเขียนด้วย

จริงๆทำ tsx เลยดีกว่าครับ 555

สรุปการทำ Component Validation มันช่วยให้การ Render มัน Smooth ไม่เจอ Error ที่ Console ช่วยทำให้ Component ของเรา มัน ยืดหยุ่น (resilient) พังตอน Dev ดีกว่าไปแตกที่ Prod ครับ ^__^

Child Component

ทำ Component ให้ Reuse ในส่วนอื่นๆได้ จะส่ง String , JSX Component เข้าไปก็ได้ เป็นต้น ตัวอย่าง

// @ts-check
import React, { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
import PropTypes from 'prop-types';

/**
 * 
 * @type {React.FC<{name: string, age?: number, address?: string, children: React.ReactNode}>}
 *
 * @returns {React.ReactNode}
 */
const SelfIntroduction = ({name = "PingkungA", age, address, children}) => {
  return (
    <div>
      <h3>My name is {name}</h3>
      {/* Conditional formatting by using short if (TERNARY operator) */}
      {age ? <h3>I&apos;m {age} years old</h3> : null}
      {age && <h3>I&apos;m {age} years old</h3>}
      {name || age }
      {/* Conditional formatting by using if */}
      {
        (() => {
          console.log(address)
          if (address) {
            return (
              <h3>I live in {address}</h3>
            )
          }
        })()
      }
      {children}
    </div>
  )
}

SelfIntroduction.propTypes = {
  name: PropTypes.string.isRequired,
  age: PropTypes.number,
  address: PropTypes.string,
  children: PropTypes.node
};

const SelfIntroYourWork = ({Jobs = []}) => {
  return (
    <div>
      {Jobs.length > 0 ? (
        <div>
          <h3>My Jobs are: </h3>
          {
            Jobs.map((job, index) => (
             <div key={index}>{index+1}.{job}</div>
            )
          )}
        </div>
      ) : null}
    </div>
  )
}

function App() {
  return (
    <div className="App"> 
      <SelfIntroduction name="PingkungA" age={33} address="Bangkok"><SelfIntroYourWork Jobs={["DOTNET Backend", "DEVOPS", "Automate Tester"]}/></SelfIntroduction>
    </div>
  )
}

export default App

ผลลัพธ์ จะประมาณนี้ mapping ด้วย เดี๋ยวงงเอง 555


Discover more from naiwaen@DebuggingSoft

Subscribe to get the latest posts sent to your email.