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'm {age} years old</h3> : null} {age && <h3>I'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'm {age} years old</h3> : null} {age && <h3>I'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'm {age} years old</h3> : null} {age && <h3>I'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'm {age} years old</h3> : null} {age && <h3>I'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.