Islands and React components
An island is an interactive component on a static page. Astro lets you write such components in React, Vue, Svelte, Preact or Solid. By default even a React component turns into plain HTML with no JavaScript; to make it work in the browser you give it a client:* directive.
Adding React
React support comes from an integration:
npx astro add reactThe command installs @astrojs/react, react and react-dom, adds react() to integrations in astro.config.mjs and sets up JSX in tsconfig.json. For Vue and Svelte the commands are the same: npx astro add vue, npx astro add svelte.
A React component
Create src/components/LikeButton.jsx, an ordinary React component with state:
// src/components/LikeButton.jsx
import { useState } from 'react';
export default function LikeButton() {
const [likes, setLikes] = useState(0);
return (
<button onClick={() => setLikes(likes + 1)}>
Likes: {likes}
</button>
);
}Inside .jsx files React rules apply, not Astro ones: className, onClick, hooks.
Putting it on a page
Import the component into the post page src/pages/posts/[id].astro and place it below the text:
---
import LikeButton from '../../components/LikeButton.jsx';
// ...the rest of the frontmatter from the dynamic routes lesson
---
<BaseLayout title={post.data.title}>
<h1>{post.data.title}</h1>
<Content />
<LikeButton client:load />
</BaseLayout>Open any post: below the text is a "Likes: 0" button, and each click increases the number. The client:load directive tells Astro to send the component code and React to the browser and bring the button to life right after the page loads. This process is called hydration.
Without a directive
Remove client:load and reload the page. The button is still there, but clicks change nothing: Astro ran the component during the build and sent only HTML. This is handy for using ready React components for non-interactive parts, such as a card layout, with no extra JavaScript.
| Markup | What the browser gets |
|---|---|
<LikeButton /> | HTML only |
<LikeButton client:load /> | HTML, the component code and React |
Island props
An island takes props just like an Astro component: <LikeButton client:load initial={5} />. The values are sent to the browser, so only simple data works: strings, numbers, arrays, objects, dates. You cannot pass a function.
Common mistake
People try to use the useState hook directly in an .astro component. Hooks are part of React and work only in .jsx and .tsx files. State in the browser is kept by the island, and .astro is responsible for the markup around it.