Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

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 react

The 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.

MarkupWhat 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.

Thanks for reading!

Donate to the site — we work hard for you.