การส่ง Props ไปยัง Islands
การส่ง props ไปยัง React island ดูเหมือนกับการส่ง props ใน JSX — syntax เหมือนกัน มีข้อจำกัดสำคัญหนึ่งอย่าง: props ที่ส่งข้าม Astro/island boundary ต้อง serialize เป็น JSON ได้
Serializable props
หัวข้อที่มีชื่อว่า “Serializable props”Astro render เพจของคุณบน server เมื่อพบ island ที่ hydrate แล้ว จะ serialize props เข้าไปใน HTML เพื่อให้ browser rehydrate component ด้วยข้อมูลเดิมทุกประการ
นั่นหมายความว่า props ต้องเป็นค่าที่ JSON สามารถแสดงได้:
- Strings, numbers, booleans
- Plain objects และ arrays (ไม่ใช่ class instances)
nullและundefined
ไม่สามารถ serialize: functions, Dates (ใช้ ISO strings แทน), class instances, React nodes, DOM elements
// React app — any prop type works,// including functions passed from a parent.<Counter start={10} label="Score" onReset={() => console.log('reset')} date={new Date()}/>---// Astro — props must be JSON-serializable.// Functions and class instances are NOT allowed// across the Astro→island boundary.import Counter from '../components/Counter.jsx';const iso = new Date().toISOString(); // Date → string ✓---<Counter start={10} label="Score" date={iso}/>{/* onReset={() => ...} would throw a build error */}Functions เป็น props: คุณไม่สามารถส่ง callback จาก
.astroไปยัง React island ได้ ถ้า island ต้องการ callback (เช่น modal ที่เรียกonClose) ให้จัดการ interaction นั้นทั้งหมดภายใน island — fetch ข้อมูล จัดการ state และ navigate โดยใช้ browser APIs ของ React
การส่ง children / slots
หัวข้อที่มีชื่อว่า “การส่ง children / slots”React ส่ง children ผ่าน prop children Astro ใช้ <slot /> เมื่อใช้ React island เป็น wrapper คุณส่งเนื้อหา HTML เข้าไปผ่าน slot mechanism ของ Astro — แต่เนื้อหา child จะเป็น HTML แบบ static ไม่ใช่ React component tree
---import Card from '../components/Card.jsx';---<Card client:load title="Hello"> <p>This content is passed as a slot — static HTML inside the React component.</p></Card>ภายใน Card.jsx เนื้อหานั้นมาถึงเป็น children เหมือนที่คาดหวัง:
export default function Card({ title, children }) { return ( <div className="card"> <h2>{title}</h2> <div>{children}</div> </div> );}Named slots
หัวข้อที่มีชื่อว่า “Named slots”Astro รองรับ named slots ภายใน React island เนื้อหา named slot มาถึงเป็น prop ที่ใช้ชื่อ slot:
---import Modal from '../components/Modal.jsx';---<Modal client:load> <h2 slot="header">Confirm deletion</h2> <p>This action cannot be undone.</p> <button slot="footer">Cancel</button></Modal>export default function Modal({ children, header, footer }) { return ( <dialog> <header>{header}</header> <main>{children}</main> <footer>{footer}</footer> </dialog> );}การเปรียบเทียบแบบเต็ม
หัวข้อที่มีชื่อว่า “การเปรียบเทียบแบบเต็ม”// React parent → React child// Any prop type, including functions and Dates.function Page() { return ( <UserCard user={userObject} // class instance ok onEdit={() => setEdit(true)} // function ok createdAt={new Date()} // Date ok /> );}---// Astro page → React island// Only JSON-serializable props allowed.import UserCard from '../components/UserCard.jsx';const user = await fetch('/api/user').then(r => r.json());---<UserCard name={user.name} avatarUrl={user.avatarUrl} createdAt={user.createdAt}/>{/* user object (plain JSON) ✓ ISO date string ✓ Function props ✗ — handle inside the island*/}