สำรวจว่า Jordan Walke และ React นำคอมโพเนนต์ที่นำกลับมาใช้ซ้ำได้, มุมมองเชิงคำประกาศ, และการเรนเดอร์ที่ขับเคลื่อนด้วย state มาใช้อย่างไร — ซึ่งเปลี่ยนสถาปัตยกรรม frontend สมัยใหม่

Jordan Walke เป็นวิศวกรซอฟต์แวร์ที่เป็นที่รู้จักจากการสร้าง React ขณะทำงานที่ Facebook ก่อน React ฝั่ง frontend มักถูกสร้างจากหน้า เทมเพลต และกอง "โค้ดกาว" ที่คอยทำให้ HTML, CSS และ JavaScript ซิงก์กันได้ Walke มีแนวคิดสำคัญคือการพลิกโมเดล: แทนที่จะมอง UI เป็นชุดเอกสารที่ต้องปะเมื่อเวลาผ่านไป ให้มองเป็นต้นไม้ของคอมโพเนนต์ขนาดเล็กที่นำกลับมาใช้ซ้ำได้ แล้วประกอบเป็นฟีเจอร์ที่ใหญ่ขึ้น
นี่ไม่ใช่แค่ไลบรารีใหม่ แต่เป็นวิธีคิดใหม่เกี่ยวกับงาน UI คอมโพเนนต์รวมชิ้นส่วนของอินเทอร์เฟซกับตรรกะและ state ที่มันต้องการ แล้วเปิดอินเทอร์เฟซที่ชัดเจน (props) ให้ส่วนอื่นของแอป นั่นทำให้การสร้าง UI รู้สึกเหมือนการประกอบบล็อกเลโกมากกว่าการแก้ไขหน้าเปราะบางหน้าเดียว
React สำคัญเพราะมันช่วยให้ทีมงาน:
เราจะพาไล่ไอเดียเชิงปฏิบัติที่ทำให้ React มีอิทธิพล:
คุณไม่จำเป็นต้องเป็นผู้เชี่ยวชาญเฟรมเวิร์กเพื่อจะตามบทความนี้ได้ เป้าหมายคือทำให้แบบจำลองทางความคิดชัดเจน—เพื่อให้คุณรู้จักรูปแบบ React ที่ดี หลีกเลี่ยงความเข้าใจผิดทั่วไป และนำหลักการเดียวกันไปใช้แม้นอก React
ก่อน React ทีมจำนวนมากสร้างอินเทอร์เฟซที่ซับซ้อนโดยเย็บเทมเพลต การจัดการ DOM แบบ jQuery และกฎ "เมื่อ X เกิด ให้อัปเดต Y" ที่เพิ่มขึ้น มันใช้ได้—จนกว่า UI จะเริ่มยุ่ง
รูปแบบทั่วไปคือ: ดึงข้อมูล เรนเดอร์ HTML แล้วผูก event handlers ที่เปลี่ยน DOM โดยตรง ทันทีที่ state เปลี่ยน (มีไอเท็มใหม่ ข้อผิดพลาดการตรวจสอบข้อมูล หรือสลับ) ใครสักคนต้องจำทุกจุดที่ขึ้นกับมัน
นั่นนำไปสู่บั๊กเช่น:
เมื่อหน้าจอพัฒนา กฎธุรกิจเดียวกันมักถูกก็อปปี้ไปหลาย handler: "ปิดปุ่มถ้าฟิลด์ว่าง", "ไฮไลท์ไอเท็มที่ยังไม่ได้อ่าน", "แสดงสถานะว่างเมื่อไม่มีผลลัพธ์" เมื่อความต้องการเปลี่ยน คุณต้องไล่ค้นไฟล์ที่ไม่เกี่ยวข้องเพื่อแก้แต่ละสำเนา
ข้อมูลสามารถโมเดลด้วยโครงสร้างไม่กี่แบบ: รายการโพสต์, ออบเจ็กต์ผู้ใช้, ชุดตัวกรอง UI เพิ่มชุดเงื่อนไข: โหลด vs โหลดเสร็จ, ข้อผิดพลาด vs สำเร็จ, อ่าน vs ยังไม่อ่าน, แก้ไข vs ดู, กรอง vs ไม่กรอง—มักเกิดพร้อมกันหลายแบบ
ลองนึกถึงฟีดข่าว:
ถ้าไม่มีกฎคาดเดาได้อย่าง "UI คือตัวฟังก์ชันของ state" คุณจะต้องประสานการแก้ไข DOM หลายครั้งที่อาจขัดแย้งกัน เป้าหมายของ React คือทำให้อัปเดตน่าเชื่อถือ: เปลี่ยนข้อมูล/สถานะ แล้ว UI จะเรนเดอร์ใหม่ให้ตรง—ทุกครั้ง
คอมโพเนนต์ คือชิ้นส่วนเล็กของอินเทอร์เฟซที่คุณสามารถตั้งชื่อ นำกลับมาใช้ และวิเคราะห์ได้ด้วยตัวเอง พูดง่ายๆ: คอมโพเนนต์รับ อินพุต แล้วส่งคืน สิ่งที่ UI ควรเป็น สำหรับอินพุตนั้น
เฟรมเวิร์ก "อินพุต → เอาต์พุต" นี้เป็นหัวใจของโมเดลคอมโพเนนต์ แทนการมองหน้าจอเป็นเทมเพลตใหญ่ ให้แบ่งเป็นบล็อกที่มีจุดประสงค์—ปุ่ม การ์ด เมนู ฟอร์ม และทั้งส่วน แล้วประกอบเข้าด้วยกัน
ใน React อินพุตที่พบบ่อยที่สุดคือ props (ย่อจาก "properties"). Props คือค่าที่คุณส่งให้คอมโพเนนต์เพื่อกำหนดค่า: ข้อความ, ตัวเลข, ธงสถานะ, event handlers หรือแม้แต่ UI อื่นๆ
เอาต์พุตคือ UI ที่คอมโพเนนต์เรนเดอร์ ถ้า props เปลี่ยน คอมโพเนนต์ก็สามารถให้เอาต์พุตที่ต่างออกไป—โดยที่คุณไม่ต้องไล่หาว่าต้องอัปเดต DOM ตรงไหน
ตัวอย่าง: คอมโพเนนต์ Button อาจรับ props เช่น label, disabled, และ onClick. UserCard อาจรับ name, avatarUrl, และ status. คุณสามารถอ่านอินเทอร์เฟซของคอมโพเนนต์ (props) เหมือนอ่านสเปกของผลิตภัณฑ์: "UI นี้ต้องการอะไรเพื่อจะแสดงได้ถูกต้อง?"
การแบ่ง UI เป็นคอมโพเนนต์ให้ผลเร็ว:
Modal, Input, หรือ Dropdown เดียวกันสามารถอยู่หลายหน้านี่คือการเปลี่ยนจากการก็อปปี้และปรับมาร์กอัปต่อหน้า คอมโพเนนต์ทำให้การทำซ้ำดูไม่จำเป็น—และท้ายที่สุดก็รับไม่ได้
React ส่งเสริมให้คุณออกแบบ UI เหมือนออกแบบระบบ: เป็นชิ้นส่วนที่ประกอบกันได้ หน้า "Checkout" กลายเป็นต้นไม้ของคอมโพเนนต์—CheckoutPage มี OrderSummary, ShippingForm, และ PaymentMethod แต่ละส่วนมีอินพุตและความรับผิดชอบที่ชัดเจน
การเปลี่ยนวิธีคิดนี้—คิดเป็นคอมโพเนนต์ก่อน—คือเหตุผลสำคัญที่ React เปลี่ยนสถาปัตยกรรม frontend มันให้ทีมมีหน่วยร่วมในการออกแบบและพัฒนา: คอมโพเนนต์
การเปลี่ยนแปลงทางความคิดที่ใหญ่ที่สุดของ React คือ UI เชิงคำประกาศ: คุณอธิบายว่าอินเทอร์เฟซควรเป็นอย่างไรสำหรับสถานะหนึ่งๆ แล้ว React จะจัดการการอัปเดตหน้าเมื่อสถานะเปลี่ยน
แทนที่จะหาองค์ประกอบด้วยตนเอง แก้ไขข้อความ สลับคลาส และคอยซิงก์ DOM คุณมุ่งที่ "รูปร่าง" ของ UI เมื่อข้อมูลเปลี่ยน UI ถูกอธิบายใหม่ และ React คำนวณชุดการเปลี่ยนแปลงขั้นต่ำที่จำเป็น
JSX เป็นวิธีสะดวกในการเขียนโครงสร้างคอมโพเนนต์โดยใช้ไวยากรณ์ที่คล้าย HTML ภายใน JavaScript. มันไม่ใช่ภาษาการเทมเพลตใหม่ที่คุณต้องเรียนรู้จากศูนย์ แต่มันคือย่อความของ "คอมโพเนนต์นี้เรนเดอร์ต้นไม้ขององค์ประกอบนี้"
ประโยชน์สำคัญคือมาร์กอัปและตรรกะที่ตัดสินใจสิ่งที่จะแสดงอยู่ด้วยกัน ซึ่งทำให้คอมโพเนนต์อ่านง่ายขึ้นในบริบทเดียว
โค้ดเชิงคำสั่งมุ่งที่ วิธีการอัปเดต UI ทีละขั้นตอน:
// Imperative: manually keep the DOM in sync
function setLoggedIn(isLoggedIn) {
const el = document.querySelector('#status');
el.textContent = isLoggedIn ? 'Welcome back' : 'Please sign in';
el.classList.toggle('ok', isLoggedIn);
el.classList.toggle('warn', !isLoggedIn);
}
โค้ดเชิงคำประกาศมุ่งที่ สิ่งที่ UI ควรเป็น สำหรับสถานะปัจจุบัน:
function Status({ isLoggedIn }) {
return (
<p className={isLoggedIn ? 'ok' : 'warn'}>
{isLoggedIn ? 'Welcome back' : 'Please sign in'}
</p>
);
}
เพราะการเรนเดอร์ถูกแสดงเป็นคำอธิบายที่ค่อนข้างบริสุทธิ์ คอมโพเนนต์มักอ่านง่าย ตรวจทานได้ง่าย และรีแฟกเตอร์ได้ง่ายกว่า นักออกแบบ วิศวกรที่เน้นผลิตภัณฑ์ และเพื่อนร่วมทีมใหม่มักตาม JSX ได้โดยไม่ต้องไล่หา event handlers และการเปลี่ยนแปลง DOM
ความชัดเจนนี้ปรับปรุงการทำงานร่วมกัน: การตัดสินใจด้าน UI มองเห็นได้ในที่เดียว และการเปลี่ยนแปลงมีแนวโน้มที่จะสร้างผลข้างเคียนที่ซ่อนอยู่ในที่อื่นน้อยลง
"State" คือข้อมูลที่สามารถเปลี่ยนได้ในขณะที่ผู้ใช้โต้ตอบกับ UI อาจเป็นข้อความในช่องค้นหา เมนูเปิด/ปิด ไอเท็มในตะกร้า หรือผลลัพธ์จากการร้องขอเครือข่าย หากมันเปลี่ยนได้และหน้าจอควรสะท้อนการเปลี่ยนแปลงนั้น มันคือ state
จุดเปลี่ยนสำคัญของ React คือการมองการเรนเดอร์เป็นผลลัพธ์ของ state ไม่ใช่ลำดับของการอัปเดต DOM แบบแมนนวล คุณอธิบายว่า UI ควรเป็นอย่างไรสำหรับ state หนึ่งๆ เมื่อ state อัปเดต React จะเรนเดอร์ส่วนที่เกี่ยวข้องใหม่
แบบจำลองนี้ต่างจาก "หาองค์ประกอบ แล้วอัปเดตข้อความ แล้วสลับคลาส" อย่างชัดเจน: แทนที่คุณจะอัปเดต DOM ให้เปลี่ยน state แล้ว UI จะอัปเดตเองเพราะมันถูกอนุมานจาก state
การไหลของข้อมูลทางเดียวหมายความว่า ข้อมูลเคลื่อนที่ในทิศทางเดียว:
สิ่งนี้ลดความประหลาดใจเพราะคุณสามารถติดตามเส้นทางของการอัปเดต: เกิดเหตุการณ์, state เปลี่ยนที่จุดเดียว, แล้ว UI เรนเดอร์จาก state ใหม่ มีความไม่แน่ใจ "ใครเปลี่ยนค่านี้" น้อยลง
function Counter() {
const [count, setCount] = React.useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Add</button>
</div>
);
}
ที่นี่ count คือ state การคลิกปุ่มจะอัปเดต state ด้วย setCount แล้ว React จะเรนเดอร์ใหม่และย่อหน้าจะแสดงตัวเลขใหม่ คุณไม่เคย "แก้ไข DOM โดยตรง"
รูปแบบเดียวกันขยายไปยังการกรองรายการ (state = ข้อความตัวกรอง, UI = รายการที่กรองแล้ว) หรือการตรวจสอบแบบฟอร์ม (state = ค่าฟิลด์และข้อผิดพลาด, UI = ข้อความ)
ไอเดียสำคัญของ React ไม่ใช่แค่ "วาดหน้าซ้ำให้เร็วขึ้น" แต่ว่า: มอง UI เป็นผลลัพธ์ของ state และเมื่อ state เปลี่ยน ให้ เปรียบเทียบสิ่งที่คุณต้องการตอนนี้ กับ สิ่งที่มีอยู่ก่อน—แล้วอัปเดตเฉพาะสิ่งที่เปลี่ยนจริงๆ
เมื่อ state หรือ props ของคอมโพเนนต์เปลี่ยน React จะเรียกคอมโพเนนต์ของคุณอีกครั้งเพื่อผลิตคำอธิบาย UI ใหม่ คิดว่ามันเหมือนการถ่ายสองสแนปชอต:
แทนที่จะล้าง DOM แล้วสร้างใหม่ React พยายามคำนวณชุดการดำเนินการ DOM ที่เล็กที่สุดที่จำเป็นเพื่อย้ายจาก A ไป B
"Virtual DOM" คือการเป็นตัวแทน UI ในหน่วยความจำของ React — ต้นไม้ขององค์ประกอบแบบเบาๆ ที่อธิบายสิ่งที่ควรปรากฏบนหน้าจอ มันไม่ใช่เบราว์เซอร์ที่สองหรือ DOM ที่เร็วกว่า มันคือโครงสร้างข้อมูลที่ React ตรวจสอบและเปรียบเทียบได้อย่างมีประสิทธิภาพ
Reconciliation คือกระบวนการ ค้นหาสิ่งที่เปลี่ยน ระหว่างต้นไม้เสมือนก่อนหน้าและต้นไม้ต่อมา React ใช้เฮียริสติกเพื่อทำให้เร็ว เช่น:
<div> ไม่ใช่ <span>)เมื่อ React รู้ว่าอะไรเปลี่ยน มันจะนำการอัปเดตเป้าหมายไปยัง DOM จริง
นี่ไม่ใช่เวทมนตร์ ประสิทธิภาพขึ้นกับรูปแบบการใช้งาน: keys ที่เสถียร, หลีกเลี่ยง re-render ที่ไม่จำเป็น, ทำงานคอมโพเนนต์ให้เล็ก และไม่คำนวณหนักในระหว่างเรนเดอร์ React ช่วยลดการสั่นของ DOM แต่ โครงสร้างคอมโพเนนต์และการไหลของข้อมูล ยังเป็นตัวกำหนดความลื่นไหลของแอป
เทคนิคการสเกลที่ใหญ่ที่สุดของ React ไม่ใช่ฟีเจอร์หรือปลั๊กอิน แต่มาจาก composition: สร้างหน้าจอโดยซ้อนคอมโพเนนต์ ส่งข้อมูลผ่าน props และใช้ children เพื่อให้คอมโพเนนต์หนึ่งๆ สามารถ "ห่อ" UI อื่นได้
เมื่อทีมใช้ composition เป็นหลัก พวกเขาหยุดคิดเป็นหน้าพิเศษและเริ่มคิดเป็นชิ้นส่วนขนาดเล็กที่เชื่อถือได้ซึ่งสามารถจัดเรียงใหม่ได้โดยไม่ต้องเขียนโค้ดใหม่ทั้งหมด
childrenการซ้อนคือเวอร์ชวลของโครงสร้าง UI: หน้าหนึ่งประกอบด้วยส่วน ซึ่งประกอบด้วยการ์ด ซึ่งประกอบด้วยปุ่ม Props คือปุ่มปรับแต่ง (ข้อความ, สถานะ, callbacks) และ children คือวิธีสร้างคอมโพเนนต์ที่กำหนดโครงสร้างแต่ให้ผู้เรียกตัดสินใจว่าสิ่งใดอยู่ภายใน
แบบจำลองที่ดี: props ปรับแต่ง, children เติมเต็ม, การซ้อนประกอบ
คอมโพเนนต์เลย์เอาต์ กำหนดโครงสร้างและระยะห่างโดยไม่เป็นเจ้าของตรรกะธุรกิจ เช่น Page, SidebarLayout, Stack, Modal. พวกมันมักพึ่งพา children มากเพื่อให้เลย์เอาต์เดียวกันห่อหลายหน้าจอได้
อินพุตที่นำกลับมาใช้ซ้ำ มาตรฐานพฤติกรรมและสไตล์ของฟอร์ม: TextField, Select, DatePicker. แทนที่จะก็อปปี้ป้าย, สถานะข้อผิดพลาด, และข้อความตรวจสอบข้ามหน้าจอ คุณรวมการตัดสินใจเหล่านี้ไว้กลางแล้วเปิด API ของ props ที่เรียบง่าย
คอมโพเนนต์รายการและไอเท็ม ทำให้ UI ที่ทำซ้ำคาดเดาได้ การแยกบ่อยคือ ItemList (ดึงข้อมูล, หน้า, สถานะว่าง) กับ ItemRow (การแสดงของไอเท็มหนึ่งชิ้น). นี่ช่วยให้เปลี่ยนการเรนเดอร์ได้ง่ายโดยไม่ทำลายการจัดการข้อมูล
Hooks เป็นวิธีสมัยใหม่ในการนำพฤติกรรมที่มีสถานะ (เช่น toggle, สถานะแบบฟอร์ม, หรือการดึงข้อมูล) ไปใช้ซ้ำข้ามคอมโพเนนต์โดยไม่บังคับให้มีรูปทรง UI เดียวกัน การแยกนี้ช่วยให้ทีมพัฒนาแบบแยกส่วนและออกแบบได้อย่างอิสระ
Composition คือวิธีที่ระบบออกแบบรักษาความสอดคล้อง: คอมโพเนนต์กลายเป็นบล็อกที่ "อนุมัติแล้ว" และเลย์เอาต์กำหนดกฎของระยะห่างและลำดับชั้น เมื่อระบบอัปเดต—สี, ตัวอักษร, สถานะการโต้ตอบ—ผลิตภัณฑ์จะรับการปรับปรุงโดยอัตโนมัติด้วยการแก้ไขน้อยกว่า
State เป็นแค่ "ข้อมูลที่เปลี่ยนได้" ใน React ที่อยู่ของ state สำคัญพอๆ กับตัวมันเอง
Local state อยู่กับคอมโพเนนต์เดียว (หรือวิดเจ็ตเล็กๆ) และไม่จำเป็นต้องอ่านจากที่อื่น ตัวอย่าง: เมนูเปิด/ปิด ค่าปัจจุบันของอินพุต หรือแท็บที่ถูกเลือก
การเก็บ state ใกล้จุดใช้งานลดการประสานและทำให้คอมโพเนนต์นำกลับมาใช้ได้ง่ายขึ้น กฎดีๆ: ถ้ามีเพียงคอมโพเนนต์เดียวที่สนใจ อย่าเผยมันไปทั้งแอป
State ที่แชร์คือข้อมูลที่หลายส่วนของ UI ต้องเห็นด้วย ตัวอย่างทั่วไปได้แก่:
เมื่อหลายคอมโพเนนต์ต้องการแหล่งความจริงเดียว การก็อปปี้ state จะนำไปสู่ความไม่ตรงกัน ("ส่วนหัวบอก 3 ไอเท็ม, หน้ารถเข็นบอก 2")
Lift state up: ย้าย state ขึ้นพาเรนต์ร่วมที่ใกล้ที่สุดแล้วส่งลงผ่าน props. นี่มักเป็นตัวเลือกที่ง่ายและทำให้การไหลของข้อมูลชัดเจน
Context: มีประโยชน์เมื่อคอมโพเนนต์หลายตัวต้องใช้ค่าเดียวกันโดยไม่ต้องส่ง props หลายชั้น เช่น ธีมหรือการยืนยันตัวตน Context เหมาะกับความกังวลระดับแอปที่ค่อนข้างคงที่
External stores: เมื่อ state ซับซ้อน (อัปเดตบ่อย, ข้อมูลอนุมานเยอะ, เวิร์กโฟลว์ข้ามหน้า) ร้านข้อมูลเฉพาะทางสามารถรวมตรรกะและการอัปเดตได้
การไหลของข้อมูลทางเดียวของ React โดดเด่นเมื่อมีเจ้าของชัดเจนสำหรับแต่ละชิ้นของ state มุ่งหาจุดรวมของความจริงที่เดียวเมื่อทำได้ และอนุมานส่วนที่เหลือ (ยอดรวม, จำนวน, รายการที่กรองแล้ว) จาก state นั้นแทนการเก็บซ้ำ
ชัยชนะที่ใหญ่ที่สุดของ React ในการทำงานจริงไม่ใช่กลเม็ดการเรนเดอร์ แต่มาจากขอบเขตคอมโพเนนต์ที่ทำให้งาน UI กลายเป็นการเปลี่ยนแปลงเล็กๆ ปลอดภัย เมื่อคอมโพเนนต์มีความรับผิดชอบชัดเจนและพื้นผิวสาธารณะที่เสถียร (props) ทีมสามารถรีแฟกเตอร์ภายในได้โดยไม่ต้องบังคับให้เขียนใหม่ทั่วทั้งแอป ความเสถียรนี้ทำให้การรีวิวโค้ดง่ายขึ้น ลดการแตกหักโดยไม่ตั้งใจ และช่วยให้เพื่อนร่วมทีมใหม่เข้าใจว่าจะทำการเปลี่ยนแปลงที่ไหน
โมเดลความคิดที่มีประโยชน์คือ: เมื่อได้รับ props และ state แล้ว คอมโพเนนต์ควรอธิบาย UI ได้อย่างคาดเดาได้ แม้ว่าจะมีผลข้างเคียงและ API ของเบราว์เซอร์ การตรรกะส่วนใหญ่ของคอมโพเนนต์ยังคงเป็นแบบกำหนดได้ นั่นคือเหตุผลที่การทดสอบ React ที่ดูแลรักษาได้มักมุ่งที่พฤติกรรมและเอาต์พุต:
การตรวจสอบการเข้าถึงเหมาะสมกับแนวทางนี้: หากทดสอบด้วย roles และชื่อที่เข้าถึงได้ คุณจะจับป้ายหาย สถานะโฟกัสผิด และความหมายที่ไม่สอดคล้องได้ตั้งแต่ต้น การตรวจสอบความสอดคล้อง (linting, formatting, การใช้ระบบออกแบบ) เสริมแนวคิดเดียวกัน: คอมโพเนนต์ที่คาดเดาได้ดูแลรักษาได้ง่ายกว่า
เมื่อคอมโพเนนต์เปิด API ของ props ขนาดเล็กและซ่อนรายละเอียดการใช้งาน ผู้คนหลายคนสามารถทำงานพร้อมกัน—คนหนึ่งปรับสไตลิง คนหนึ่งเปลี่ยนการดึงข้อมูล อีกคนอัปเดตการทดสอบ—โดยไม่ชนกัน
ประสิทธิภาพของ React มักเกี่ยวกับ "งานที่แอปขอให้เบราว์เซอร์ทำ" มากกว่า "React ช้า" UI ที่เร็วสุดคืองานน้อยที่สุด: จำนวนโหนด DOM น้อย การคำนวณ layout/reflow น้อย การคำนวณหนักน้อย และการเรียกเครือข่ายน้อย
ปัญหาทั่วไปคือ re-render ที่ไม่จำเป็น: การเปลี่ยน state เล็กๆ ทำให้ subtree ขนาดใหญ่เรนเดอร์ซ้ำเพราะ state อยู่สูงเกินไป หรือ props เปลี่ยนตัวตนทุกครั้ง (สร้างอ็อบเจ็กต์/ฟังก์ชันใหม่แบบ inline)
อีกปัญหาคลาสสิกคือ ลิสต์ยาว—ร้อยหรือพันแถวที่มีรูปภาพ การจัดรูปแบบ และ event handlers แม้แต่ละแถวจะ "ถูก" แต่รวมกันแล้วงานทั้งหมดจะมากและการเลื่อนจะสะดุดเพราะเบราว์เซอร์ตามไม่ทัน
เริ่มจากโครงสร้าง:
นอกจากนี้ให้โฟกัสที่สิ่งที่ผู้ใช้สัมผัส: ลดความหน่วงของอินพุต, เร่งจุดแสดงผลสำคัญครั้งแรก, และทำให้การโต้ตอบลื่นไหล การปรับปรุง 20ms ในการโต้ตอบที่ใช้บ่อยอาจสำคัญกว่าการลด 200ms ในหน้าจอที่ใช้ไม่บ่อย
Derived state คือข้อมูลที่คุณสามารถคำนวณจาก state/props อื่น (เช่น fullName จาก firstName + lastName หรือรายการที่กรองจากรายการ + คำค้น) การเก็บมันมักสร้างบั๊ก: คุณมีแหล่งความจริงสองแห่งที่อาจไม่ตรงกัน
ชอบการคำนวณค่าที่อนุมานได้ในระหว่างเรนเดอร์ (หรือ memoize ถ้าคำนวณหนัก) เก็บเฉพาะสิ่งที่ไม่สามารถอนุมานได้—โดยทั่วไปคือการป้อนของผู้ใช้ การตอบจากเซิร์ฟเวอร์ และเจตนาของ UI (เช่น "พาเนลเปิดอยู่ไหม?")
React ไม่เพียงแค่นำเสนอวิธีเขียน UI ที่ดีขึ้น มันยังกระตุ้นทีมให้จัดระเบียบการสร้าง แชร์ และดูแล frontend ใหม่ ก่อนที่คอมโพเนนต์จะกลายเป็นรูปแบบคิดเริ่มต้น หลายโปรเจกต์มักมอง UI เป็นหน้าพร้อมสคริปต์กระจัดกระจาย แต่กับ React หน่วยสถาปัตยกรรมเริ่มกลายเป็นคอมโพเนนต์: ชิ้นของ UI ที่มี API ชัด (props) และพฤติกรรมที่คาดเดาได้
React เข้ากันได้ดีกับการเติบโตของ single-page applications (SPAs). เมื่อการเรนเดอร์ถูกขับเคลื่อนด้วย state "หน้า" หยุดเป็นเทมเพลตที่ส่งจากเซิร์ฟเวอร์ และเริ่มเป็นการประกอบคอมโพเนนต์บวกการ routing ฝั่งไคลเอนต์ การเปลี่ยนแปลงนี้ทำให้โค้ดมักจัดรอบพื้นที่ฟีเจอร์และชิ้นส่วน UI ที่นำกลับมาใช้ได้ แทนที่จะจัดรอบไฟล์ HTML แยกกัน
เมื่อ UI ถูกสร้างจากชิ้นส่วนที่นำกลับมาใช้ได้ ธรรมชาติคือการมาตรฐานชิ้นส่วนนั้น องค์กรหลายแห่งย้ายจากการก็อปปี้มาร์กอัปไปสู่การสร้างไลบรารีคอมโพเนนต์: ปุ่ม คอนโทรลฟอร์ม โมดัล primitive เลย์เอาต์ และรูปแบบเช่นสถานะว่าง เมื่อเวลาผ่านไป ไลบรารีเหล่านี้มักพัฒนาเป็นระบบออกแบบ—คอมโพเนนต์ร่วมกับแนวทาง—เพื่อให้ทีมส่งมอบประสบการณ์ที่สอดคล้องกันโดยไม่คิดใหม่สำหรับทุกหน้าจอ
คอมโพเนนต์กระตุ้นให้ทีมตั้งชื่อสิ่งเดียวกัน เมื่อทุกคนพูดถึง <Button>, <Tooltip>, หรือ <CheckoutSummary> การสนทนาจะเป็นรูปธรรมมากขึ้น: ผู้คนสามารถคุยพฤติกรรมและขอบเขต ไม่ใช่แค่ภาพลักษณ์ คำศัพท์ร่วมกันยังช่วยให้เพื่อนร่วมทีมใหม่เรียนรู้ได้เร็วขึ้น เพราะระบบค้นพบได้ผ่านโค้ด
ความสำเร็จของ React มีอิทธิพลต่อแนวคิดการพัฒนา UI ทั่วไป: การพัฒนาแบบ component-first, การเรนเดอร์เชิงคำประกาศ, และการไหลของข้อมูลที่คาดเดาได้กลายเป็นความคาดหวัง แม้เฟรมเวิร์กอื่นจะมีรายละเอียดการทำงานต่างกัน แนวปฏิบัติเหล่านี้ก็ถูกนำไปปรับใช้เพราะพิสูจน์แล้วว่าเร็วขึ้นสำหรับทีมจริง
React ได้ชื่อเสียงจากการทำให้ UI ซับซ้อนพัฒนาได้ง่ายขึ้น แต่ก็ไม่ฟรี รู้ข้อแลกเปลี่ยนตั้งแต่แรกช่วยให้ทีมเลือกใช้ด้วยเหตุผลที่ถูกต้อง—และเลี่ยงการทำตามโดยไม่เข้าใจ
React มีช่วงการเรียนรู้: คอนเซ็ปต์คอมโพเนนต์, hooks, และแบบจำลองเช่นการอัปเดต state และ effects ต้องใช้เวลาเพื่อเข้าใจ นอกจากนี้ React สมัยใหม่มักต้องการ tooling (bundling, linting, TypeScript เป็นตัวเลือกที่พบบ่อย) ซึ่งเพิ่มการตั้งค่าและการดูแลรักษา สุดท้าย React นำชั้นนามธรรมมามาก—ไลบรารีคอมโพเนนต์, routing, รูปแบบการดึงข้อมูล—ที่อาจเป็นประโยชน์ แต่ก็อาจซ่อนความซับซ้อนได้จนกว่าจะเกิดปัญหา
"React เป็นแค่ view." ในทางทฤษฎีใช่; ในทางปฏิบัติ React กำหนดสถาปัตยกรรมคุณอย่างมาก ขอบเขตคอมโพเนนต์ ความเป็นเจ้าของ state และรูปแบบการประกอบมีผลต่อการไหลของข้อมูลและการจัดระเบียบโค้ด
"Virtual DOM เร็วเสมอ." Virtual DOM เน้นการอัปเดตที่คาดเดาได้และประสบการณ์นักพัฒนา React สามารถเร็ว แต่ประสิทธิภาพขึ้นกับรูปแบบการเรนเดอร์, memoization, ขนาดรายการ, และการหลีกเลี่ยง re-render ที่ไม่จำเป็น
React เหมาะกับแอปที่มีสถานะโต้ตอบเยอะ ฐานโค้ดยืนยาว และมีหลายคนทำงานพร้อมกัน สำหรับเว็บไซต์การตลาดที่คงที่ส่วนใหญ่หรือวิดเจ็ตเล็กๆ ตัวเลือกที่เรียบง่ายกว่า (เทมเพลตฝั่งเซิร์ฟเวอร์, JS น้ำหนักเบา, หรือเฟรมเวิร์กมินิมอล) อาจง่ายต่อการส่งมอบและดูแลรักษามากกว่า
ถ้าคุณกำลังทำต้นแบบแอป React และอยากทดสอบแนวคิดอย่างรวดเร็ว (ขอบเขตคอมโพเนนต์, การเป็นเจ้าของ state, รูปแบบการประกอบ) กระบวนการสร้างแบบแชทสามารถช่วยได้ ตัวอย่างเช่น Koder.ai ให้คุณอธิบายฟีเจอร์ในแชทแล้วสร้าง frontend React ที่ทำงานได้พร้อม backend Go/PostgreSQL จากนั้นปรับด้วย snapshots/rollback และส่งออกซอร์สโค้ดเมื่อคุณพร้อมจะควบคุมด้วยตนเอง เป็นวิธีปฏิบัติที่ดีในการทดสอบการตัดสินใจด้านสถาปัตยกรรมบนฟีเจอร์จริงก่อนจะผูกมัดกับการพัฒนาเต็มรูปแบบ
ถัดไป: ทำต้นแบบฟีเจอร์จริงหนึ่งชิ้น วัดความซับซ้อนและความเร็วทีม แล้วขยายรูปแบบด้วยความตั้งใจ—ไม่ใช่โดยดีฟอลต์
Jordan Walke สร้าง React ในขณะที่ทำงานที่ Facebook. React มีความสำคัญเพราะมันแทนที่โค้ด “กาว” ที่แก้ไข DOM แบบเปราะบางด้วยแนวทางที่อิงคอมโพเนนต์และขับเคลื่อนด้วย state—ทำให้การจัดการอินเทอร์เฟซที่ซับซ้อนง่ายขึ้นในการขยาย ตรวจสอบข้อผิดพลาด และดูแลรักษา.
เทมเพลตมักกระจายกฎของ UI ไว้ในมาร์กอัปพร้อมกับ handlers กระจัดกระจาย ("เมื่อ X เกิด ให้อัปเดต Y"). คอมโพเนนต์รวม UI กับตรรกะไว้หลังอินเทอร์เฟซเล็กๆ (props) ดังนั้นคุณจึงสามารถประกอบฟีเจอร์จากชิ้นส่วนที่คาดเดาได้ แทนที่จะคอยปะหน้ากระดาษไปเรื่อยๆ.
คอมโพเนนต์คือหน่วยที่นำกลับมาใช้ซ้ำได้ ซึ่งรับอินพุต (มักเป็น props) และคืนสิ่งที่ UI ควรเป็นสำหรับอินพุตนั้นๆ.
ในทางปฏิบัติ ควรตั้งเป้าไว้ว่า:
Props คืออินพุตที่คุณส่งให้คอมโพเนนต์เพื่อตั้งค่ามัน (ข้อความ, ค่าสถานะ, callback หรือ UI อื่นๆ). มอง props เป็นสัญญา:
disabled, onSubmit) แทนวัตถุรวมๆUI เชิงคำประกาศหมายถึงคุณอธิบาย สิ่งที่ อินเทอร์เฟซควรเป็นสำหรับสถานะปัจจุบัน แทนที่จะอธิบาย วิธี อัปเดต DOM ทีละขั้นตอน.
โดยปฏิบัติ:
JSX คือไวยากรณ์ที่ให้คุณเขียนโครงสร้าง UI ในลักษณะที่ดูเหมือน HTML ภายใน JavaScript. ข้อดีคือตรรกะการเรนเดอร์และมาร์กอัปอยู่ด้วยกัน ทำให้คอมโพเนนต์อ่านและตรวจทานได้ง่ายขึ้นเป็นหน่วยเดียว.
State คือข้อมูลที่เปลี่ยนได้เมื่อผู้ใช้โต้ตอบและที่หน้าจอควรสะท้อนการเปลี่ยนแปลงนั้น (ข้อความในช่องค้นหา, สถานะการโหลด, ของในตะกร้า ฯลฯ).
กฎปฏิบัติ: เก็บแหล่งความจริง (ข้อมูลที่ผู้ใช้ป้อน, ตอบจากเซิร์ฟเวอร์, เจตนาของ UI) แล้วคำนวณค่าที่อนุมานได้แทนการเก็บซ้ำ.
การไหลของข้อมูลทางเดียวหมายถึง:
สิ่งนี้ช่วยให้การดีบักง่ายขึ้นเพราะคุณสามารถติดตามเส้นทางของการอัปเดตได้ตรง: เหตุการณ์ → การเปลี่ยนแปลง state → การเรนเดอร์ใหม่.
Virtual DOM คือการแทน UI ในหน่วยความจำของ React. เมื่อ state/props เปลี่ยน React จะเปรียบเทียบคำอธิบาย UI ก่อนหน้าและปัจจุบัน แล้วอัปเดต DOM จริงเฉพาะที่จำเป็น.
เพื่อหลีกเลี่ยงปัญหาทั่วไป:
key ที่เสถียรสำหรับรายการเริ่มจากเรียบง่ายแล้วขยับออกไปเมื่อจำเป็น:
ชอบแหล่งความจริงเดียวเมื่อเป็นไปได้ และอนุมานค่าอื่นๆ แทนการเก็บซ้ำ