Skip to content

astro

Build your first Astro island

Astro

Build your first Astro island

Build your first Astro island

Use a Preact component to greet your visitors with a randomly-selected welcome message!

  • Add Preact to your Astro project
  • Include Astro islands (Preact .jsx components) on your home page
  • Use client: directives to make islands interactive

Add Preact to your Astro project

1. If it’s running, quit the dev server to have access to the terminal (keyboard shortcut: Ctrl + C).
  1. Add the ability to use Preact components in your Astro project with a single command:

    ```sh npx astro add preact ``` ```sh pnpm astro add preact ``` ```sh yarn astro add preact ```
  2. Follow the command line instructions to confirm adding Preact to your project.

Include a Preact greeting banner

This component will take an array of greeting messages as a prop and randomly select one of them to show as a welcome message. The user can click a button to get a new random message.

1. Create a new file in `src/components/` named `Greeting.jsx`
Note the `.jsx` file extension. This file will be written in Preact, not Astro.
  1. Add the following code to Greeting.jsx:

    import { useState } from 'preact/hooks';
    
    export default function Greeting({messages}) {
    
      const randomMessage = () => messages[(Math.floor(Math.random() * messages.length))];
      
      const [greeting, setGreeting] = useState(messages[0]);
    
      return (
        <div> 
          <h3>{greeting}! Thank you for visiting!</h3>
          <button onClick={() => setGreeting(randomMessage())}>
            New Greeting
          </button>
        </div>
      );
    }
  2. Import and use this component on your Home page index.astro.

    ---
    import BaseLayout from '../layouts/BaseLayout.astro';
    import Greeting from '../components/Greeting';
    const pageTitle = "Home Page";
    ---
    <BaseLayout pageTitle={pageTitle}>
      <h2>My awesome blog subtitle</h2>
      <Greeting messages={["Hi", "Hello", "Howdy", "Hey there"]} />
    </BaseLayout>

    Check the preview in your browser: you should see a random greeting, but the button won't work!

  3. Add a second <Greeting /> component with the client:load directive.

    ---
    import BaseLayout from '../layouts/BaseLayout.astro';
    import Greeting from '../components/Greeting';
    const pageTitle = "Home Page";
    ---
    <BaseLayout pageTitle={pageTitle}>
      <h2>My awesome blog subtitle</h2>
      <Greeting messages={["Hi", "Hello", "Howdy", "Hey there"]} />
      <Greeting client:load messages={["Hej", "Hallo", "Hola", "Habari"]} />
    </BaseLayout>
  4. Revisit your page and compare the two components. The second button works because the client:load directive tells Astro to send and rerun its JavaScript on the client when the page loads, making the component interactive. This is called a hydrated component.

  5. Once the difference is clear, remove the non-hydrated Greeting component.

    ---
    import BaseLayout from '../layouts/BaseLayout.astro';
    import Greeting from '../components/Greeting';
    const pageTitle = "Home Page";
    ---
    <BaseLayout pageTitle={pageTitle}>
      <h2>My awesome blog subtitle</h2>
      <Greeting messages={["Hi", "Hello", "Howdy", "Hey there"]} />
      <Greeting client:load messages={["Hej", "Hallo", "Hola", "Habari"]} />
    </BaseLayout>

Analyze the Pattern

There are other client: directives to explore. Each sends the JavaScript to the client at a different time. client:visible, for example, will only send the component's JavaScript when it is visible on the page.

Consider an Astro component with the following code:

---




---
<BaseLayout>
  <AstroBanner />
  <PreactBanner />
  <PreactBanner client:load />
  <SvelteCounter />
  <SvelteCounter client:visible />
</BaseLayout>
  1. Which of the five components will be hydrated islands, sending JavaScript to the client?

    `` and `` will be hydrated islands.

  2. In what way(s) will the two <PreactBanner /> components be the same? In what way(s) will they be different?

    **Same**: They both show the same HTML elements and look the same initially. **Different**: The component with the `client:load` directive will rerender after the page is loaded, and any interactive elements that it has will work.

  3. Assume the SvelteCounter component shows a number and has a button to increase it. If you couldn't see your website's code, only the live published page, how would you tell which of the two <SvelteCounter /> components used client:visible?

    Try clicking the button, and see which one is interactive. If it responds to your input, it must have had a `client:` directive.

Test your knowledge

For each of the following components, identify what will be sent to the browser:

  1. <ReactCounter client:load />

  2. <SvelteCard />

Checklist

- [ ] I can install an Astro integration. - [ ] I can write UI framework components in their own language. - [ ] I can use a `client:` directive for hydration on my UI framework component.

Resources