ข้ามไปยังเนื้อหา

เช็คลิสต์รีวิวโค้ด

นี่คือเช็คลิสต์ที่ต้องไล่ดู — ด้วยตา บน diff ไหนก็ตาม ของคุณเองหรือของ AI — หลังจากเครื่องมือใน Verification Tools รันแล้วผ่านสะอาด มันตั้งใจให้จบในหน้าเดียวที่พิมพ์ได้: เช็คลิสต์ที่ไม่มีใครเปิดจริง ๆ ตอนรีวิวก็ไร้ค่า ทุกบรรทัดลิงก์ไปบทที่อธิบายว่า ทำไม หน้านี้เลยยังคงเป็น list ไม่ใช่การรันคอร์สซ้ำ กลุ่มต่าง ๆ เรียงตามลำดับเดียวกับ วิธีอ่านโค้ด React ที่คุณไม่ได้เขียน

flowchart LR
  H["Hooks and deps"] --> P["Partial tool coverage<br/>(eslint-plugin-react-hooks catches some; behavior needs a test)"]
  B["Boundary and directives"] --> M["Mostly human review<br/>(a real RSC framework build is the only real check)"]
  K["Keys and identity"] --> M
  S["State ownership"] --> P
  E["Effects vs events"] --> M
  C["Memo and compiler"] --> M
อะไรจับแต่ละกลุ่มได้จริง ถ้ามี
  • dependency array ของทุก useEffect/useMemo/useCallback มีทุกอย่างที่ callback อ่านจริง ๆ ครบไหม? ดู useEffect & Effects
  • ค่าที่เปลี่ยนบ่อย (callback, theme) ถูกอ่านผ่าน useEffectEvent แทนที่จะถูกตัดออกจาก deps ของ effect เงียบ ๆ ไหม? ดู AI Bug Catalog entry 2
  • ทุก hook ถูกเรียกแบบ unconditional ที่ top level ในลำดับเดียวกันทุก render — ไม่เคยหลัง return ก่อนเวลา ไม่เคยข้างใน if ใช่ไหม? ดู AI Bug Catalog entry 3
  • useRef<T>() ได้รับค่าเริ่มต้นแบบชัดเจนเสมอไหม (null สำหรับ DOM ref)? ดู TypeScript with React
  • โค้ดใหม่รับ ref เป็น prop ธรรมดาแทนการห่อตัวเองด้วย forwardRef ไหม? ดู useRef & the DOM
  • getSnapshot ของทุก useSyncExternalStore return primitive หรือ reference ที่ cache ไว้ ไม่เคยเป็น object/array literal ใหม่ใช่ไหม? ดู External Stores
  • ทุก promise ที่ส่งให้ use() ถูกอ่านจาก cache ที่เสถียร ไม่เคยถูกสร้างใหม่ใน render body ตรง ๆ ใช่ไหม? ดู use() & Data Fetching
  • โค้ด import useActionState จาก react ไม่ใช่ useFormState จาก react-dom ใช่ไหม? ดู AI Bug Catalog entry 8
  • ทุกไฟล์ที่เรียก client-only hook (useState, useEffect) หรือแปะ event handler มี 'use client' จริง ๆ บนตัวเองหรือ parent ใน project ที่รองรับ RSC จริงไหม? ดู Server Components
  • ทุก prop ที่ข้ามจาก Server Component ไป Client Component ยังเป็นข้อมูล serializable ธรรมดา (หรือ Server Action จริง) ไม่เคยเป็น function เปล่า ๆ หรือ class instance ใช่ไหม? ดู Server Components
  • dangerouslySetInnerHTML เคยได้รับ content จาก user โดยไม่ผ่าน sanitizer จริงก่อนไหม? ดู AI Bug Catalog entry 11
  • setter ของ useOptimistic (หรือ requestFormReset) ถูกเรียกจากข้างใน startTransition/Action เสมอ ไม่เคยตรง ๆ จาก event handler ธรรมดาใช่ไหม? ดู Forms & useOptimistic
  • ทุก .map() ที่วน list ใช้ id ที่เสถียรจากข้อมูลเป็น key — ไม่เคยเป็น array index และไม่เคยขาดหายไปเลยใช่ไหม? ดู AI Bug Catalog entry 13–14
  • .map() ที่จับกลุ่ม sibling element ใช้ <Fragment key={...}> (import มาแบบชัดเจน) ไม่ใช่ shorthand <> ใช่ไหม? ดู AI Bug Catalog entry 15
  • component editor/detail ใช้ key={currentItemId} เพื่อบังคับ reset สะอาด ๆ เมื่อเรื่องที่มันแสดงเปลี่ยน แทนที่จะสะสม internal state ที่ค้างอยู่ใช่ไหม? ดู Rendering & Reconciliation
  • state ตัวนี้คำนวณได้ตอน render แทนที่จะ sync จาก prop ด้วย useEffect ไหม? ดู useEffect & Effects
  • setState เคยถูกเรียกตรง ๆ ข้างใน render body นอกเหนือ event handler หรือ effect ไหม? ดู AI Bug Catalog entry 17
  • ทุก state update ของ object/array เป็น reference ใหม่จริง ๆ ไม่เคยเป็นการ mutate ด้วย .push/assign ตรง ๆ แล้วเรียก setter ด้วย reference เดิมใช่ไหม? ดู State Snapshot & Purity
  • value ของ provider ใน Context ถูก memoize (useMemo) และมีแค่ข้อมูลที่เปลี่ยนช้าและแชร์กว้าง ไม่เคยเป็นค่าที่เปลี่ยนทุก keystroke ใช่ไหม? ดู Context
  • ทุกการเรียก set หลัง await ข้างใน startTransition(async () => {...}) อยู่ข้างใน startTransition ของตัวเองอีกชั้นไหม? ดู Transitions
  • data fetch ข้างใน effect ยกเลิก request ที่ค้างอยู่ก่อนหน้า (AbortController) เมื่อ identifier ของมันเปลี่ยนเร็วไหม? ดู useEffect & Effects
  • มี Date.now()/Math.random() ที่ถูกอ่านตอน render ในโค้ดที่จะ hydrate สักวันไหม — แทนที่จะอยู่ข้างใน effect เท่านั้นหรือส่งลงมาเป็น prop คงที่? ดู AI Bug Catalog entry 22
  • useLayoutEffect อ่านค่าที่มีแค่ useEffect ตัวพี่น้องเขียน โดยคาดหวังว่าจะเห็น write ของ commit ปัจจุบันแทนที่จะเป็นของ commit ก่อนหน้าไหม? ดู Commit Phase & Effects
  • ทุก prop ที่ส่งให้ component ที่ห่อด้วย memo เก็บ reference ที่เสถียร — ไม่มี object/array/function literal แบบ inline ที่จุดเรียกใช้ใช่ไหม? ดู Memoization & the Compiler
  • ถ้า project อ้างว่ารัน React Compiler babel-plugin-react-compiler ถูกต่อสายเข้า build จริงไหม — หรือโค้ดแค่สมมติว่ามี auto-memoization ที่จริง ๆ ไม่ได้รันอยู่? ดู The React Compiler
  • return type ของ component ที่ annotate เป็น JSX.Element/ReactElement เคยต้อง return null ไหม? ควรเป็น ReactNode แทนหรือเปล่า? ดู TypeScript with React
ทำไม 'value ของ provider ใน Context ถูก memoize ไหม' ถึงอยู่กลุ่ม 'ใครเป็นเจ้าของ state' แทนที่จะเป็น 'Memo pairing กับสมมติฐานของ compiler'?
กลุ่มไหนในเช็คลิสต์จับเรื่องนี้ได้ และจับได้อย่างไร?
useLayoutEffect(() => {
  if (boxRef.current) setMeasuredWidth(parseInt(boxRef.current.style.width, 10));
});
useEffect(() => {
  if (boxRef.current) boxRef.current.style.width = expand ? '200px' : '100px';
}, [expand]);
ทำไมเช็คลิสต์ถึงถามเจาะจงว่า .map() ที่จับกลุ่ม sibling ใช้ <Fragment key={...}> (import มาแบบชัดเจน) แทนที่จะถามแค่ 'ทุก list item มี key ไหม'?
กลุ่มไหนในเช็คลิสต์ครอบคลุม diff นี้ และมันถามว่าอะไร?
export default function ProductPage({ id }) {
  function handleAddToCart() { console.log('added', id); }
  return <AddToCartButton onAdd={handleAddToCart} />;
}
เช็คลิสต์บอกให้เช็คว่า 'Date.now()/Math.random() ถูกอ่านตอน render ในโค้ดที่จะ hydrate สักวันไหม' ทำไมเงื่อนไข 'จะ hydrate สักวัน' ถึงสำคัญ?