Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 29 additions & 30 deletions src/pages/en/tutorial/6-islands/1.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ setup: |

- add Preact to your Astro project
- include Astro islands (Preact `.jsx` components) on your home page
- use different `client:` directives for each island to customize JavaScript sent to the browser
- use `client:` directives to make islands interactive

</PreCheck>

Expand All @@ -32,7 +32,7 @@ setup: |

## Preact Greeting Banner

This component will randomly select one of four greetings and use it in a welcome message.
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`

Expand All @@ -42,21 +42,31 @@ This component will randomly select one of four greetings and use it in a welcom

```jsx title="src/components/Greeting.jsx"
import { h } from 'preact'
import { useState } from 'preact/hooks';

export default function Greeting({messages}) {

const randomMessage = () => messages[(Math.floor(Math.random() * messages.length))];

const [greeting, setGreeting] = useState(randomMessage());

export default function Banner({messages}) {
const greeting = messages[(Math.floor(Math.random() * 4))];
return (
<h3>{greeting}! Thank you for visiting!</h3>
<div>
<h3>{greeting}! Thank you for visiting!</h3>
<button onClick={() => setGreeting(randomMessage())}>
New Greeting
</button>
</div>
);
}
```

3. Import and use this component on your Home page `index.astro`. Note that `jsx` files are imported without their file extension:
3. Import and use this component on your Home page `index.astro`.

```astro title="src/pages/index.astro" ins={3,8}
---
import BaseLayout from '../layouts/BaseLayout.astro';
import Greeting from '../components/Greeting';
import Greeting from '../components/Greeting.jsx';
const pageTitle = "Home Page"
---
<BaseLayout pageTitle={pageTitle}>
Expand All @@ -65,6 +75,9 @@ This component will randomly select one of four greetings and use it in a welcom
</BaseLayout>
```

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


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

```astro title="src/pages/index.astro" ins={9} "client:load"
Expand All @@ -80,29 +93,15 @@ This component will randomly select one of four greetings and use it in a welcom
</BaseLayout>
```

### Build your site

To see the difference in client-side behavior between these components, you will need to view your built site.

1. To view your built site locally, quit the dev server and run the following two commands to first, build your site to a local folder and then, run the preview of that build.

```sh
npm run build

npm run preview
```
:::tip
You can also check your built site by committing your current progress to GitHub and then waiting for Netlify to automatically build and republish your site to the web.
:::

2. Refresh the page several times and compare the behavior of the two greeting messages, noticing whether they do or do not update.

Don't forget to restart the dev server before continuing if you are previewing your build locally!
5. 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 to the _client_ when the page _loads_, making the component interactive. We call this a **hydrated** component.


<Box icon="question-mark">

### 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:

```astro
Expand All @@ -121,17 +120,17 @@ import SvelteCounter from '../components/SvelteCounter.svelte';
</BaseLayout>
```

1. Which of the five components will be **hydrated islands**, sending JavaScript to the client that will run even after the site has been built?
1. Which of the five components will be **hydrated** islands, sending JavaScript to the client?

|| `<PreactBanner client:load />` and `<SvelteCounter client:visible />` 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 render the same HTML elements and look the same. Different: One will be generated at build time and will not rerender until your site is rebuilt. It will look the same until your site is rebuilt. The one with a client directive will execute its JavaScript on every page refresh, showing an updated component. ||
|| **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. If you couldn't see your website's code, only the live published page, how would you tell which `<SvelteCounter />` component used `client:visible`?
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 />` component used `client:visible`?

|| Try clicking the buttons, and see which one is interactive. The one that is interactive has a client directive, because its JavaScript to increase and decrease the counter in response to button clicks has been sent to the client. ||
|| Try clicking the button, and see which one is interactive. If it responds to your input, it must have had a `client:` directive. ||
</Box>

## Before you go
Expand Down Expand Up @@ -172,7 +171,7 @@ For each of the following components, identify what will be sent to the browser:
<Checklist key="framework">
- [ ] I can install an Astro integration using the command `astro add` in the terminal.
- [ ] I can write UI framework components in their own language, with their own native extention, then import and use them in `.astro` components alongside my Astro components.
- [ ] I can choose whether to use a `client:directive` to control hydration on my UI framework component, depending on when I want its JavaScript to run.
- [ ] I can choose whether to use a `client:` directive to control hydration on my UI framework component.
</Checklist>
</Box>

Expand Down
100 changes: 0 additions & 100 deletions src/pages/en/tutorial/6-islands/2.md

This file was deleted.

43 changes: 15 additions & 28 deletions src/pages/en/tutorial/6-islands/4.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,30 @@ Let's build an clickable icon to let your users toggle betwen light or dark mode
```astro title="src/components/ThemeIcon.astro"
---
---
<span onclick="handleToggleClick()">
<div id="themeToggle">
<svg width="30px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path class="sun" fill-rule="evenodd" d="M12 17.5a5.5 5.5 0 1 0 0-11 5.5 5.5 0 0 0 0 11zm0 1.5a7 7 0 1 0 0-14 7 7 0 0 0 0 14zm12-7a.8.8 0 0 1-.8.8h-2.4a.8.8 0 0 1 0-1.6h2.4a.8.8 0 0 1 .8.8zM4 12a.8.8 0 0 1-.8.8H.8a.8.8 0 0 1 0-1.6h2.5a.8.8 0 0 1 .8.8zm16.5-8.5a.8.8 0 0 1 0 1l-1.8 1.8a.8.8 0 0 1-1-1l1.7-1.8a.8.8 0 0 1 1 0zM6.3 17.7a.8.8 0 0 1 0 1l-1.7 1.8a.8.8 0 1 1-1-1l1.7-1.8a.8.8 0 0 1 1 0zM12 0a.8.8 0 0 1 .8.8v2.5a.8.8 0 0 1-1.6 0V.8A.8.8 0 0 1 12 0zm0 20a.8.8 0 0 1 .8.8v2.4a.8.8 0 0 1-1.6 0v-2.4a.8.8 0 0 1 .8-.8zM3.5 3.5a.8.8 0 0 1 1 0l1.8 1.8a.8.8 0 1 1-1 1L3.5 4.6a.8.8 0 0 1 0-1zm14.2 14.2a.8.8 0 0 1 1 0l1.8 1.7a.8.8 0 0 1-1 1l-1.8-1.7a.8.8 0 0 1 0-1z"/>
<path class="moon" fill-rule="evenodd" d="M16.5 6A10.5 10.5 0 0 1 4.7 16.4 8.5 8.5 0 1 0 16.4 4.7l.1 1.3zm-1.7-2a9 9 0 0 1 .2 2 9 9 0 0 1-11 8.8 9.4 9.4 0 0 1-.8-.3c-.4 0-.8.3-.7.7a10 10 0 0 0 .3.8 10 10 0 0 0 9.2 6 10 10 0 0 0 4-19.2 9.7 9.7 0 0 0-.9-.3c-.3-.1-.7.3-.6.7a9 9 0 0 1 .3.8z"/>
</svg>
</span>
</div>

<style>
.sun { fill: black; }
.moon { fill: transparent; }


:global(.dark) .sun { fill: transparent; }
:global(.dark) .moon { fill: white; }
</style>

```

2. Add the icon to `Header.astro` so that it will be displayed on all pages. Don't forget to import the component.

```astro title="src/components/Header.astro" ins={4,9}
---
import Hamburger from './components/Hamburger.astro';
import Navigation from './components/Navigation.astro';
import ThemeIcon from './components/ThemeIcon.astro';
import Hamburger from './Hamburger.astro';
import Navigation from './Navigation.astro';
import ThemeIcon from './ThemeIcon.astro';
---
<header>
<nav>
Expand Down Expand Up @@ -83,11 +83,11 @@ Choose some alternate colors to use in dark mode.

## Add client-side interactivity

Instead of a framework component island, you can use a `<script>` tag with the directiive `is:inline`. This script can check and set `localStorage` as well as toggle CSS themes when the icon is clicked.
To add interactivity to an Astro component, you can use a `<script>` tag. This script can check and set the current theme from `localStorage` and toggle the theme when the icon is clicked.

1. Add the following `<script>` tag in `src/components/ThemeIcon.astro` after your `<style>` tag:

```astro title="src/components/ThemeIcon.astro" ins={9-35}
```astro title="src/components/ThemeIcon.astro" ins={9-37}
<style>
.sun { fill: black; }
.moon { fill: transparent; }
Expand All @@ -96,7 +96,7 @@ Instead of a framework component island, you can use a `<script>` tag with the d
:global(.dark) .moon { fill: white; }
</style>

<script is:inline>
<script>
const theme = (() => {
if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
return localStorage.getItem('theme');
Expand All @@ -122,6 +122,8 @@ Instead of a framework component island, you can use a `<script>` tag with the d
const isDark = element.classList.contains("dark");
localStorage.setItem("theme", isDark ? "dark" : "light");
}

document.getElementById("themeToggle").addEventListener("click", handleToggleClick);
</script>
```

Expand Down Expand Up @@ -149,7 +151,7 @@ Choose whether each of the following statements describes Astro `<script>` tags,
</Option>
</MultipleChoice>

2. They will create static elements on your site unless you include a `client:directive` to send their JavaScript to the client and run in the browser.
2. They will create static elements on your site unless you include a `client:` to send their JavaScript to the client and run in the browser.

<MultipleChoice>
<Option>
Expand All @@ -163,7 +165,7 @@ Choose whether each of the following statements describes Astro `<script>` tags,
</Option>
</MultipleChoice>

2. They allow you to "try out" a new framework without requiring you to start an entire new project using that tech stack.
3. They allow you to "try out" a new framework without requiring you to start an entire new project using that tech stack.

<MultipleChoice>
<Option>
Expand All @@ -177,20 +179,6 @@ Choose whether each of the following statements describes Astro `<script>` tags,
</Option>
</MultipleChoice>

3. They can be reused on multiple pages by adding them to several Astro components, and/or in an Astro layout component.

<MultipleChoice>
<Option>
Astro `<script>` tags
</Option>
<Option>
UI framework components
</Option>
<Option isCorrect>
both
</Option>
</MultipleChoice>

4. They allow you to reuse code you have written in other frameworks and you can often just drop them right into your site.

<MultipleChoice>
Expand All @@ -205,7 +193,7 @@ Choose whether each of the following statements describes Astro `<script>` tags,
</Option>
</MultipleChoice>

5. They allow you to create a fully-functional, interactive and dynamic website without needing to know or learn any other JavaScript frameworks.
5. They allow you to add interactivity without needing to know or learn any other JavaScript frameworks.

<MultipleChoice>
<Option isCorrect>
Expand All @@ -226,8 +214,7 @@ Choose whether each of the following statements describes Astro `<script>` tags,

<Checklist key="theme">

- [ ] I can use multiple `<script>` tags in the same Astro component.
- [ ] I can use the `is:inline` attribute on a `<script>` tag
- [ ] I can use a `<script>` tag to add interactivity to an Astro component

</Checklist>
</Box>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/en/tutorial/6-islands/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ In this unit, you'll use **Astro islands** to bring frontend framework component

You will:
- Add a UI framework, Preact, to your Astro project
- Use Preact to create a greeting component and an interactive quote generator
- Use Preact to create an interactive greeting component
- Learn when you might _not_ choose islands for interactivity

## Before you go
Expand Down