Islands & Using React in Astro
In a React app, the whole UI is one giant JavaScript bundle. The browser downloads it, hydrates the entire component tree, and only then does the page become interactive. Astro flips that model: the page is static HTML by default and you opt individual components into hydration — those are your islands.
The killer feature for React developers: your existing React components work inside Astro with zero changes. Drop in a Counter.jsx, add client:load, done. Everything around it stays pure HTML.
What this module covers
Section titled “What this module covers”| Lesson | What you will learn |
|---|---|
| What is an Island? | Partial hydration vs full-app hydration; the performance case |
| Using React in Astro | npx astro add react; drop any .jsx component into .astro |
| Client Directives | client:load, client:idle, client:visible, client:media, client:only |
| Passing Props | Serializable props; passing children/slots to framework islands |
| When to Use an Island | Default-static strategy; isolation vs a React SPA’s single tree |
The core idea
Section titled “The core idea”// In a React/Next.js app every component// is part of one hydrated tree.// The whole bundle ships to the browser.
export default function Page() { return ( <Layout> <Header /> {/* hydrated */} <HeroImage /> {/* hydrated */} <ArticleText /> {/* hydrated */} <Counter /> {/* hydrated */} <Footer /> {/* hydrated */} </Layout> );}---// In Astro, only Counter needs JS.// Everything else is static HTML.import Header from '../components/Header.astro';import Counter from '../components/Counter.jsx';---<Header /> <!-- static HTML, zero JS --><img src="/hero.jpg" alt="Hero" /> <!-- static HTML --><article>Long article text...</article> <!-- static HTML --><Counter client:load /> <!-- ONE hydrated island --><footer>...</footer> <!-- static HTML -->