Composition Patterns
Composition คือ pattern พื้นฐาน
หัวข้อที่มีชื่อว่า “Composition คือ pattern พื้นฐาน”คำตอบเรื่องการ reuse ของ React ไม่ใช่ inheritance แต่คือ composition แทนที่จะ extend component คุณส่ง content และ behavior เข้าไป ใน component รูปแบบง่ายที่สุดคือ prop children: component รับ JSX อะไรก็ได้ แล้วตัดสินใจว่าจะวางไว้ตรงไหน
// Card ทั่วไปที่ไม่รู้และไม่สนว่าข้างในมีอะไรfunction Card({ title, children }) { return ( <section className="card"> <h3>{title}</h3> <div className="card-body">{children}</div> </section> );}
<Card title="Profile"> <Avatar user={user} /> <p>{user.bio}</p></Card>คุณส่ง JSX ผ่าน prop ตัวไหนก็ได้ ไม่ใช่แค่ children — <Layout sidebar={<Nav />} main={<Feed />} /> ก็คือ composition นี่คือวิธีเลี่ยง prop-drilling ลึก ๆ และ inheritance tree ที่แข็งทื่อ
Compound components
หัวข้อที่มีชื่อว่า “Compound components”เมื่อหลาย component ต้องทำงานร่วมกันและ แชร์ state pattern compound component จะเปิดเผยกลุ่มชิ้นส่วนที่ประสานงานกันผ่าน state ที่แชร์ (มักผ่าน context) — ส่วนผู้ใช้จัดวางชิ้นส่วนเหล่านั้นได้อย่างอิสระ
// ผู้ใช้ compose ชิ้นส่วนเอง; Tabs แชร์ state ผ่าน context ภายใน<Tabs defaultValue="a"> <TabList> <Tab value="a">First</Tab> <Tab value="b">Second</Tab> </TabList> <TabPanel value="a">Panel A</TabPanel> <TabPanel value="b">Panel B</TabPanel></Tabs>ภายใน Tabs ให้ค่า active + setter ผ่าน context; Tab และ TabPanel อ่านด้วย useContext ผู้ใช้ได้ API ที่ clean และ declarative พร้อมควบคุม layout เต็มที่ โดยไม่ต้องร้อย props ผ่านทุกชิ้น นี่คือวิธีที่ library อย่าง Radix และ Headless UI จัดโครงสร้าง component
flowchart TB tabs["Tabs (ให้ value + setValue ผ่าน context)"] --> list["TabList"] list --> tab["Tab (อ่าน context, เรียก setValue)"] tabs --> panel["TabPanel (อ่าน context, แสดงถ้า active)"]
Render props และทำไม hook มาแทนส่วนใหญ่
หัวข้อที่มีชื่อว่า “Render props และทำไม hook มาแทนส่วนใหญ่”render prop คือ prop ที่ค่าเป็น function ที่ return JSX — ให้ component แชร์ logic ส่วนผู้เรียกควบคุม การ render
// Render prop: MouseTracker เป็นเจ้าของ logic, ผู้เรียก render เอง<MouseTracker render={({ x, y }) => <p>Cursor at {x}, {y}</p>} />render props เป็นวิธีคลาสสิกในการแชร์ stateful logic ก่อนมี hook วันนี้ custom hook ทำแบบเดียวกันได้ตรงกว่า — ไม่มี wrapper component ไม่มีการซ้อน:
// เทียบเท่าสมัยใหม่: custom hookfunction Component() { const { x, y } = useMousePosition(); // แชร์ logic ผ่าน hook return <p>Cursor at {x}, {y}</p>; // ผู้เรียก render ตามปกติ}คุณยังจะ เห็น render props อยู่ (บาง library ใช้ และ children-เป็น-function ก็คืออันหนึ่ง) แต่สำหรับการแชร์ logic ของคุณเอง หยิบ custom hook มาก่อน
Controlled vs uncontrolled
หัวข้อที่มีชื่อว่า “Controlled vs uncontrolled”input จะเป็น controlled เมื่อ React state เป็น single source of truth (value + onChange) และเป็น uncontrolled เมื่อ DOM ถือค่าไว้และคุณอ่านผ่าน ref (หรือใน React 19 อ่านจาก FormData ของ form ตอน submit)
// Controlled: state ขับ input; validate/transform ได้ทุก keystrokeconst [name, setName] = useState("");<input value={name} onChange={(e) => setName(e.target.value)} />
// Uncontrolled: DOM เป็นเจ้าของค่า; อ่านตอนที่ต้องการconst ref = useRef(null);<input defaultValue="Ada" ref={ref} /> // ref.current.value ตอน submitใช้ controlled เมื่อต้อง react หรือจำกัด input ระหว่างที่เปลี่ยน; ใช้ uncontrolled สำหรับ form ง่าย ๆ ที่สนใจแค่ค่าสุดท้าย (state น้อยกว่า, re-render น้อยกว่า)