Skip to content

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.

LessonWhat you will learn
What is an Island?Partial hydration vs full-app hydration; the performance case
Using React in Astronpx astro add react; drop any .jsx component into .astro
Client Directivesclient:load, client:idle, client:visible, client:media, client:only
Passing PropsSerializable props; passing children/slots to framework islands
When to Use an IslandDefault-static strategy; isolation vs a React SPA’s single tree
React
// 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>
);
}
Astro
---
// 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 -->
What does Astro ship to the browser by default for a plain .astro component?
What makes an Astro component an 'island'?
Do your existing React components need to be rewritten to work as Astro islands?