Controlled vs Uncontrolled Components ใน React Form ต่างกันอย่างไร
การทำฟอร์มใน React เลือกได้ทั้งแบบให้ React คุมค่าผ่าน state หรือปล่อยให้ DOM จัดการค่าเอง แต่ทั้งสองแบบเหมาะกับคนละสถานการณ์ ขึ้นอยู่กับว่าฟอร์มต้องตอบสนองระหว่างพิมพ์มากแค่ไหน

Controlled vs Uncontrolled Components ใน React Form ต่างกันอย่างไร
เวลาเขียนฟอร์มใน React คำถามที่หลายคนเจอเร็วมากคือ ควรเก็บค่าของ input ไว้ใน state หรือปล่อยให้ DOM เป็นคนถือค่าเอง คำตอบคือทำได้ทั้งสองแบบ แต่แนวคิดและวิธีใช้งานต่างกันค่อนข้างชัดเจน
ภาพรวมสั้น ๆ คือ
- Controlled Component: React เป็นคนคุมค่า
- Uncontrolled Component: DOM เป็นคนคุมค่า
การเลือกใช้จึงไม่ได้มีคำตอบตายตัวว่าแบบไหนดีกว่าเสมอไป แต่ขึ้นอยู่กับลักษณะของฟอร์มและพฤติกรรมที่เราต้องการจากผู้ใช้
Controlled Component คืออะไร
Controlled Component คือฟอร์มที่ React เป็นเจ้าของข้อมูลทั้งหมดของ input โดยค่าจะถูกเก็บไว้ใน state และอัปเดตผ่าน onChange ทุกครั้งที่ผู้ใช้พิมพ์
ตัวอย่างเช่น
const [email, setEmail] = useState('')
<input value={email} onChange={e => setEmail(e.target.value)} />
ในกรณีนี้ source of truth อยู่ที่ React state ไม่ใช่ DOM นั่นหมายความว่า DOM มีหน้าที่เพียงแสดงผลตามค่าที่ React ส่งลงไปเท่านั้น
ข้อดีของ Controlled Component
ข้อดีสำคัญของการใช้ Controlled Component คือเราควบคุมพฤติกรรมของฟอร์มได้ละเอียดมาก เพราะค่าทุกอย่างอยู่ใน state แล้ว
เหมาะกับงานที่ต้องการความ interactive สูง เช่น
- ตรวจสอบความถูกต้องของข้อมูลทันทีระหว่างพิมพ์
- ปิดปุ่ม submit ถ้ายังกรอกข้อมูลไม่ครบ
- format ข้อมูลอัตโนมัติ เช่น เบอร์โทร หรือการแปลงตัวพิมพ์เล็กใหญ่
- sync ค่าจาก input ไปยังส่วน preview แบบ real-time
- แสดง field เพิ่มหรือลดตามค่าที่ผู้ใช้กรอก
เมื่อ React ถือข้อมูลทั้งหมดอยู่แล้ว การเชื่อมค่ากับ UI ส่วนอื่นจึงทำได้ง่ายและชัดเจน
ข้อเสียของ Controlled Component
แม้จะยืดหยุ่นมาก แต่ Controlled Component ก็มาพร้อมต้นทุนที่สูงขึ้นในด้านโค้ดและการดูแลรักษา
ตัวอย่างปัญหาที่เจอบ่อยคือ
- โค้ดเยอะขึ้น เพราะต้องมี state และ handler สำหรับแต่ละ field
- ฟอร์มขนาดใหญ่จะซับซ้อนขึ้นเร็วมาก
- ต้องจัดการเรื่อง error, touched, validation state เพิ่มเติม
- หากออกแบบไม่ดี อาจเกิด re-render บ่อยเกินจำเป็น
- อ่านและ maintain ยากขึ้นเมื่อจำนวน field เพิ่มขึ้น
ดังนั้นถ้าฟอร์มมีหลายช่องและไม่ได้ต้องตอบสนองแบบทันทีเสมอไป การใช้ controlled ทั้งหมดอาจทำให้โค้ดบวมเกินจำเป็น
Uncontrolled Component คืออะไร
Uncontrolled Component คือการปล่อยให้ input จัดการค่าของตัวเองผ่าน DOM โดย React จะไม่อัปเดต state ทุกครั้งที่ผู้ใช้พิมพ์ แต่จะอ่านค่าจาก ref เมื่อต้องการใช้งาน เช่น ตอน submit
ตัวอย่างเช่น
const inputRef = useRef(null)
<input ref={inputRef} defaultValue="hello" />
เมื่อถึงเวลาส่งฟอร์ม จึงค่อยอ่านค่าผ่าน
inputRef.current.value
ในรูปแบบนี้ source of truth อยู่ที่ DOM ไม่ใช่ React state
defaultValue กับ value ต่างกันอย่างไร
จุดที่สำคัญมากสำหรับ Uncontrolled Component คือการใช้ defaultValue แทน value
defaultValueหมายถึงค่าเริ่มต้นของ input- หลังจาก render ครั้งแรกแล้ว DOM จะเป็นคนดูแลค่าต่อเอง
ในขณะที่
valueหมายถึง React กำลังบอกว่า input นี้ต้องมีค่าเป็นแบบนี้เสมอ
ดังนั้นถ้าใส่ value แต่ไม่มี onChange ผู้ใช้จะพิมพ์ไม่ได้ เพราะ React ล็อกค่าไว้แล้ว ปัญหานี้เป็นจุดที่มือใหม่เจอบ่อยมาก
ข้อดีของ Uncontrolled Component
Uncontrolled Component เหมาะกับฟอร์มที่ไม่ต้องตอบสนองระหว่างพิมพ์มากนัก และต้องการลดภาระในการจัดการ state
ข้อดีหลัก ๆ ได้แก่
- โค้ดสั้นและเรียบง่ายกว่า
- ไม่ต้องสร้าง state สำหรับทุก field
- ลดจำนวน re-render ได้ดี
- เหมาะกับฟอร์มขนาดใหญ่ที่ไม่ได้ต้องควบคุมทุกค่าตลอดเวลา
- ทำงานได้ดีกับไลบรารีที่ใช้แนวทาง
ref
ตัวอย่างงานที่เหมาะ เช่น
- search box
- newsletter signup
- ฟอร์มที่อ่านค่าตอนกด submit เท่านั้น
- งานที่ใช้ form library อย่าง React Hook Form
แล้วควรเลือกแบบไหน
การเลือกใช้ขึ้นอยู่กับว่าค่าของ input มีผลต่อ UI ระหว่างที่ผู้ใช้กำลังพิมพ์หรือไม่
กรณีที่ควรใช้ Controlled
เลือกใช้ Controlled เมื่อเราต้อง “รู้ค่าตลอดเวลา” เช่น
- แสดง error แบบทันที
- สร้าง preview แบบ real-time
- มี conditional field
- ทำ wizard form
- มี logic ที่ UI ต้องตอบสนองตามค่าที่กำลังถูกกรอก
กรณีที่ควรใช้ Uncontrolled
เลือกใช้ Uncontrolled เมื่อเราต้อง “รู้ค่าตอนจบ” เช่น
- ฟอร์ม login ง่าย ๆ
- ช่องกรอกที่ไม่ต้องตอบสนองทันที
- ฟอร์มที่อ่านค่าตอน submit อย่างเดียว
- ฟอร์มจำนวน field เยอะและต้องการเน้น performance
สิ่งที่ควรระวัง
อีกเรื่องที่สำคัญคือไม่ควรสลับ input เดียวกันไปมาระหว่าง controlled และ uncontrolled เพราะ React จะเตือนทันทีหากมันไม่แน่ใจว่าใครเป็นคนควบคุมค่า
ตัวอย่างปัญหาที่พบบ่อยคือ
- ตอนแรก
valueเป็นundefined - ต่อมากลายเป็น
string
React จะมองว่านี่คือการเปลี่ยนจาก uncontrolled ไปเป็น controlled หรือกลับกัน ซึ่งไม่ควรเกิดขึ้นใน input เดียวกัน
แนวทางแก้คือกำหนดค่าเริ่มต้นให้ชัดเจนตั้งแต่แรก เช่น
const [name, setName] = useState('')
วิธีนี้ช่วยให้ React รู้ชัดเจนตั้งแต่ต้นว่า input นี้ถูกควบคุมโดย state
ภาพจำสั้น ๆ
ถ้าจะสรุปให้จำง่ายที่สุด
- Controlled = React ถือรีโมต
- Uncontrolled = DOM ถือรีโมต
หรือพูดอีกแบบคือ
- ถ้าต้อง รู้ค่าตลอดเวลา ให้ React คุม
- ถ้าต้อง รู้ค่าตอนจบ ให้ DOM คุม
สรุป
Controlled และ Uncontrolled Components เป็นสองแนวทางที่ใช้ได้จริงทั้งคู่ในการทำฟอร์มด้วย React ความต่างไม่ได้อยู่ที่ว่าแบบไหนถูกกว่า แต่อยู่ที่ว่าแบบไหนเหมาะกับลักษณะของฟอร์มนั้นมากกว่า
ถ้าฟอร์มต้อง interactive สูง ต้อง validate ระหว่างพิมพ์ หรือมี UI ที่เปลี่ยนตามค่า input การใช้ Controlled จะชัดเจนและจัดการง่ายกว่า แต่ถ้าฟอร์มเรียบง่าย เน้นอ่านค่าตอน submit หรือมี field จำนวนมาก การใช้ Uncontrolled หรือ form library ที่ช่วยจัดการผ่าน ref อาจทำให้โค้ดกระชับและประสิทธิภาพดีกว่า
เมื่อเข้าใจหลักคิดนี้แล้ว การออกแบบ React form จะง่ายขึ้นมาก และช่วยลดการเขียนโค้ดเกินความจำเป็นได้อย่างชัดเจน