พร็อพส์สำหรับเรนเดอร์และรูปแบบ HOC
ส่งฟังก์ชันเรนเดอร์เป็นพร็อพเพื่อเติม UI และครอบคอมโพเนนต์ด้วย Higher-Order Components เพื่อเติมพฤติกรรมโดยไม่แก้ไขคอมโพเนนต์ต้นฉบับ
พร็อพส์สำหรับเรนเดอร์และรูปแบบ HOC เป็นบทเรียน Frontend Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Frontend Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Frontend Academy มีบทเรียนทั้งหมด 4 บทเรียน
รูปแบบการนำกลับมาใช้ซ้ำแบบคลาสสิกสองรูปแบบ
ก่อนมีฮุกใน React 16.8 การนำตรรกะที่มีสถานะกลับมาใช้ใหม่หมายถึงการเลือกใช้ คอมโพเนนต์ลำดับสูง (HOCs) หรือ พร็อพส์สำหรับเรนเดอร์ รูปแบบเหล่านี้พบได้น้อยในโค้ดใหม่ แต่คุณยังจะพบในโค้ดเบสเดิมและไลบรารีจำนวนมาก
พร็อพส์สำหรับเรนเดอร์ — แนวคิด
คอมโพเนนต์จะรับฟังก์ชันเป็นพร็อพส์ ซึ่งมักตั้งชื่อว่า render หรือ children แล้วเรียกใช้ฟังก์ชันนั้นพร้อมสถานะภายใน ผู้ใช้คอมโพเนนต์จะเป็นผู้กำหนดว่าจะเรนเดอร์อะไรด้วยสถานะดังกล่าว
function Mouse({ render }) {
const [pos, setPos] = useState({ x: 0, y: 0 });
useEffect(() => {
const handler = (e) => setPos({ x: e.clientX, y: e.clientY });
window.addEventListener('mousemove', handler);
return () => window.removeEventListener('mousemove', handler);
}, []);
return render(pos);
}
// Usage:
<Mouse render={({ x, y }) => <p>{x}, {y}</p>} />children ในฐานะฟังก์ชัน
พร็อพส์ children สามารถเป็นฟังก์ชันได้เช่นกัน เป็นรูปแบบเดียวกันแต่มี JSX ที่อ่านง่ายกว่า
function Mouse({ children }) {
const [pos, setPos] = useState({ x: 0, y: 0 });
/* ... */
return children(pos);
}
<Mouse>
{({ x, y }) => <p>{x}, {y}</p>}
</Mouse>คอมโพเนนต์ลำดับสูง — แนวคิด
HOC คือฟังก์ชันที่รับคอมโพเนนต์หนึ่งตัวแล้วคืนคอมโพเนนต์ใหม่ที่มีพร็อพส์หรือพฤติกรรมเพิ่มเติม มีการใช้อย่างมากใน connect() ของ Redux และ withRouter() ของ React Router
function withMouse(Component) {
return function WithMouse(props) {
const [pos, setPos] = useState({ x: 0, y: 0 });
useEffect(() => {
const handler = (e) => setPos({ x: e.clientX, y: e.clientY });
window.addEventListener('mousemove', handler);
return () => window.removeEventListener('mousemove', handler);
}, []);
return <Component {...props} mouse={pos} />;
};
}
// Usage:
const Position = ({ mouse }) => <p>{mouse.x}, {mouse.y}</p>;
const EnhancedPosition = withMouse(Position);
<EnhancedPosition />คอมโพเนนต์ลำดับสูงประกอบกันด้วยการครอบ
คุณสามารถซ้อนคอมโพเนนต์ลำดับสูงหลายตัวได้ แต่จะเกิด “นรกของตัวครอบ” ซึ่งแก้ไขข้อผิดพลาดได้ยาก
// Multiple HOCs:
const Enhanced = withRouter(connect(mapState)(withTranslation()(MyComponent)));
// Equivalent in modern React:
// const Enhanced = MyComponent (reads from hooks: useRouter, useSelector, useTranslation)พร็อพส์สำหรับเรนเดอร์กับคอมโพเนนต์ลำดับสูง
พร็อพส์สำหรับเรนเดอร์มีความชัดเจนกว่า เป็นมิตรต่อระบบชนิด และไม่มีชื่อชนกัน ส่วนคอมโพเนนต์ลำดับสูงมีลักษณะเป็นการประกาศมากกว่า แต่ชนิดแบบคงที่ของคอมโพเนนต์ที่ถูกครอบอาจสูญหายหากไม่ระวัง และชื่อพร็อพส์อาจชนกันได้
เหตุใดฮุกจึงเข้ามาแทนที่ทั้งสองรูปแบบ
ฮุกกำหนดเองบรรลุเป้าหมายเดียวกันด้วยขั้นตอนประกอบที่น้อยกว่า ไม่ต้องมีคอมโพเนนต์ตัวครอบ ไม่ต้องมีอาร์กิวเมนต์ฟังก์ชันซ้อนกัน และไม่ต้องใช้เทคนิคซับซ้อนกับชนิด ฮุกคือคำตอบตามแนวทางของปี 2025
// Custom hook equivalent of useMouse:
function useMouse() {
const [pos, setPos] = useState({ x: 0, y: 0 });
useEffect(() => {
const handler = (e) => setPos({ x: e.clientX, y: e.clientY });
window.addEventListener('mousemove', handler);
return () => window.removeEventListener('mousemove', handler);
}, []);
return pos;
}
// Usage:
const { x, y } = useMouse();เมื่อใดที่พร็อพส์สำหรับเรนเดอร์ยังเหมาะกว่า
เหมาะกับคอมโพเนนต์ที่ต้องแทรกมาร์กอัป ไม่ใช่เพียงสถานะ เช่น รายการเสมือนที่เรนเดอร์รายการในตำแหน่งเฉพาะ พร็อพส์สำหรับเรนเดอร์ยังคงเป็นรูปแบบที่เหมาะสมตามธรรมชาติ
function VirtualList({ items, itemHeight, renderItem }) {
const [scrollTop, setScrollTop] = useState(0);
const start = Math.floor(scrollTop / itemHeight);
const visible = items.slice(start, start + 20);
return visible.map((item, i) => renderItem(item, start + i));
}
<VirtualList items={data} itemHeight={40} renderItem={(item, i) => (
<Row key={i} data={item} />
)} />แนวทางปฏิบัติที่ดีสำหรับคอมโพเนนต์ลำดับสูง (เมื่อจำเป็น)
หากจำเป็นต้องเขียน HOC ให้คัดลอกเมธอดแบบคงที่ด้วย hoist-non-react-statics ส่งต่อการอ้างอิงด้วย React.forwardRef และคง displayName ไว้สำหรับ DevTools
การส่งต่อการอ้างอิงในคอมโพเนนต์ลำดับสูง
โดยค่าเริ่มต้น คอมโพเนนต์ลำดับสูงจะซ่อนการอ้างอิงไว้ ให้ใช้ forwardRef เพื่อให้ผู้ใช้ยังเข้าถึงการอ้างอิงของคอมโพเนนต์พื้นฐานได้
function withLogger(Component) {
const Wrapped = React.forwardRef((props, ref) => {
console.log('rendering', Component.name);
return <Component {...props} ref={ref} />;
});
Wrapped.displayName = `withLogger(${Component.name})`;
return Wrapped;
}การจดจำรูปแบบจากโค้ดเดิม
คุณจะพบคอมโพเนนต์ลำดับสูงและพร็อพส์สำหรับเรนเดอร์ใน react-redux ซึ่งเป็นอินเทอร์เฟซรุ่นเก่า, Apollo Client v2, react-router v5 ซึ่งมี withRouter, Formik ซึ่งมี Field และ styled-components ซึ่งมี withTheme เมื่ออินเทอร์เฟซรุ่นใหม่ของไลบรารีเหล่านี้รองรับแล้ว ให้ปรับโครงสร้างไปใช้ฮุก
ตรวจสอบอย่างรวดเร็ว
ฮุกเข้ามาแทนที่รูปแบบใดเป็นส่วนใหญ่ในการแชร์ตรรกะที่มีสถานะระหว่างคอมโพเนนต์รีแอ็กต์
ทบทวน: พร็อพส์สำหรับเรนเดอร์และคอมโพเนนต์ลำดับสูง
พร็อพส์สำหรับเรนเดอร์คือฟังก์ชันในฐานะพร็อพส์ที่คืนค่า JSX มีความชัดเจนและเป็นมิตรต่อระบบชนิด คอมโพเนนต์ลำดับสูงคือฟังก์ชันที่ครอบคอมโพเนนต์ และใช้ในไลบรารีรุ่นเก่า เช่น connect และ withRouter ฮุกกำหนดเองเข้ามาแทนที่ทั้งสองรูปแบบสำหรับตรรกะสถานะ พร็อพส์สำหรับเรนเดอร์ยังเหมาะกว่าเมื่อจำเป็นต้องแทรกมาร์กอัปแบบกำหนดเอง เช่น รายการเสมือน เมื่อเขียน HOC ให้ใช้ forwardRef ย้ายพร็อพเพอร์ตีแบบคงที่ และกำหนด displayName
คำถามที่พบบ่อย
บทเรียน “พร็อพส์สำหรับเรนเดอร์และรูปแบบ HOC” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “พร็อพส์สำหรับเรนเดอร์และรูปแบบ HOC” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Frontend Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Frontend Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “พร็อพส์สำหรับเรนเดอร์และรูปแบบ HOC”
ส่งฟังก์ชันเรนเดอร์เป็นพร็อพเพื่อเติม UI และครอบคอมโพเนนต์ด้วย Higher-Order Components เพื่อเติมพฤติกรรมโดยไม่แก้ไขคอมโพเนนต์ต้นฉบับ คุณปฏิบัติ Frontend Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Frontend Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Frontend Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “พร็อพส์สำหรับเรนเดอร์และรูปแบบ HOC” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Frontend Academy นี้ได้ไหม
ได้ บทเรียน Frontend Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- คอมโพเนนต์แบบประกอบร่วมกับ Context
- พร็อพส์สำหรับเรนเดอร์และรูปแบบ HOC
- พอร์ทัลสำหรับโมดัลและทูลทิป
- ขอบเขตข้อผิดพลาด