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

การส่ง Props ไปยัง Islands

การส่ง props ไปยัง React island ดูเหมือนกับการส่ง props ใน JSX — syntax เหมือนกัน มีข้อจำกัดสำคัญหนึ่งอย่าง: props ที่ส่งข้าม Astro/island boundary ต้อง serialize เป็น JSON ได้

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
// 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
---
// 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

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 เหมือนที่คาดหวัง:

src/components/Card.jsx
export default function Card({ title, children }) {
return (
<div className="card">
<h2>{title}</h2>
<div>{children}</div>
</div>
);
}

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>
src/components/Modal.jsx
export default function Modal({ children, header, footer }) {
return (
<dialog>
<header>{header}</header>
<main>{children}</main>
<footer>{footer}</footer>
</dialog>
);
}
React
// 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
---
// 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
*/}
ทำไม props ที่ส่งไปยัง Astro island จึงต้อง JSON-serializable?
ข้อใดไม่ใช่ prop ที่ valid สำหรับส่งจาก .astro ไปยัง React island?
เนื้อหา slot/children ที่ส่งไปยัง React island จาก .astro มาถึง component อย่างไร?