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

เมื่อใดควรใช้ Island

ปรัชญาหลักของ Astro นั้นเรียบง่าย: เริ่มต้นด้วย static แล้ว opt เข้า JS เฉพาะเมื่อต้องการ นี่คือตรงข้ามกับ React SPA ที่ทุกอย่างเป็น JavaScript จนกว่าคุณจะลงแรงตัด JavaScript ออก

ถามคำถามนี้สำหรับทุก component บนเพจ:

“Component นี้ตอบสนองต่อ user interaction หรือเปลี่ยนแปลงตามเวลาใน browser หรือไม่?”

ถ้า ใช่ — ทำให้เป็น island ด้วย client:* directive ที่เหมาะสม ถ้า ไม่ — คงไว้เป็น .astro component หรือ React component ที่ไม่มี directive (render เป็น HTML แบบ static)

React
// In a React/Next.js app everything is a component.
// Making something "static" requires extra effort.
export default function BlogPage({ post, related }) {
return (
<div>
{/* These are all in the React tree, all hydrated */}
<Header /> {/* purely presentational */}
<ArticleContent post={post} /> {/* purely presentational */}
<LikeButton postId={post.id} /> {/* interactive */}
<ShareMenu url={post.url} /> {/* interactive */}
<RelatedPosts posts={related} />{/* purely presentational */}
</div>
);
}
Astro
---
// In Astro, ask "does this need JS?" for each piece.
import Header from '../components/Header.astro'; // no JS
import ArticleContent from '../components/ArticleContent.astro'; // no JS
import LikeButton from '../components/LikeButton.jsx'; // needs JS
import ShareMenu from '../components/ShareMenu.jsx'; // needs JS
import RelatedPosts from '../components/RelatedPosts.astro'; // no JS
const { post, related } = Astro.props;
---
<Header />
<ArticleContent post={post} />
<LikeButton client:visible postId={post.id} />
<ShareMenu client:idle url={post.url} />
<RelatedPosts posts={related} />

ในหน้าบล็อกโพสต์ทั่วไป มีเพียงสอง islands (LikeButton และ ShareMenu) ที่ส่ง JavaScript ทุกอย่างอื่นเป็น HTML ที่ไม่มี JS

นี่คือความแตกต่างทางสถาปัตยกรรมที่สำคัญที่สุดจาก React SPA ในแอป React มี component tree เดียว React Context ไหลจาก top-level Provider ลงไปยัง descendant ใดก็ได้ ไม่ว่าจะลึกแค่ไหน

ใน Astro แต่ละ island เป็น React root แยกกัน Context ไม่ข้าม island boundaries

// This does NOT work across islands:
//
// .astro page:
// <ThemeProvider client:load> ← island A
// <ThemedButton client:load /> ← island B (separate root!)
//
// ThemeProvider's context is not visible to ThemedButton.

ตัวเลือกที่ 1 — ห่อทั้งสองใน single island:

---
import ThemedApp from '../components/ThemedApp.jsx';
---
<ThemedApp client:load />
// ThemedApp.jsx — one island, one React root, context works
import { ThemeProvider } from './ThemeContext';
import ThemedButton from './ThemedButton';
export default function ThemedApp() {
return (
<ThemeProvider>
<ThemedButton />
</ThemeProvider>
);
}

ตัวเลือกที่ 2 — ใช้ shared signal/store ภายนอก React:

Libraries อย่าง nanostores (tiny store ที่ Astro แนะนำ) ให้ islands แชร์ state โดยไม่ต้องมี React root ร่วมกัน:

src/stores/theme.js
import { atom } from 'nanostores';
export const theme = atom('light');
// island A
import { useStore } from '@nanostores/react';
import { theme } from '../stores/theme';
export default function ThemeToggle() {
const t = useStore(theme);
return <button onClick={() => theme.set(t === 'light' ? 'dark' : 'light')}>{t}</button>;
}
// island B — reads the same store
import { useStore } from '@nanostores/react';
import { theme } from '../stores/theme';
export default function ThemedButton() {
const t = useStore(theme);
return <button class={t}>Click me</button>;
}
Componentต้องการ hydration?ใช้อะไร
Navigation headerไม่ (แค่ links).astro component
Hero imageไม่<img> ใน .astro
Article bodyไม่.astro component
ปุ่ม Like / upvoteใช่ — click handlerReact island client:visible
Comment sectionใช่ — fetch + renderReact island client:visible
Mobile menu toggleใช่ — open/close stateReact island client:media
Page layoutไม่.astro layout
Date formatterไม่ (build-time).astro หรือ React แบบ static
Navigation bar ที่ render เฉพาะ links ไม่มี dropdown ไม่มี state ควรเป็นอะไรใน Astro?
React islands สองอันบนหน้า Astro เดียวกันต้องการแชร์ theme state วิธีที่ถูกต้องคืออะไร?
ทำไม React Context จึงไม่ทำงานข้าม two separate islands โดยค่าเริ่มต้น?
Astro-native solution ที่แนะนำสำหรับการแชร์ reactive state ระหว่างหลาย islands คืออะไร?