How to Use Islands in Fresh Framework in Deno
In Fresh, use
islands to add interactive client-side components by exporting them from the islands/ directory and importing them in your pages. This enables partial hydration, letting only those components run JavaScript in the browser while the rest stays server-rendered.Syntax
In Fresh, an island is a client-side interactive component placed inside the islands/ folder. You import it into your page and use it like a normal component. Fresh automatically hydrates it on the client.
islands/Component.tsx: The interactive component file.import Component from '../islands/Component.tsx': Importing the island in a page.<Component />: Using the island in JSX.
tsx
import { h } from "preact"; import { useState } from "preact/hooks"; export default function Counter() { const [count, setCount] = useState(0); return ( <button onClick={() => setCount(count + 1)}> Count: {count} </button> ); }
Example
This example shows a simple counter island component that increments a number on button click. The island is imported and used in the main page, which is server-rendered but hydrates the island for interactivity.
tsx
/// islands/Counter.tsx import { h } from "preact"; import { useState } from "preact/hooks"; export default function Counter() { const [count, setCount] = useState(0); return ( <button onClick={() => setCount(count + 1)}> Count: {count} </button> ); } /// routes/index.tsx import { h } from "preact"; import Counter from "../islands/Counter.tsx"; export default function Home() { return ( <main> <h1>Welcome to Fresh Islands Demo</h1> <Counter /> </main> ); }
Output
<main>
<h1>Welcome to Fresh Islands Demo</h1>
<button>Count: 0</button>
</main>
Common Pitfalls
- Placing interactive components outside the
islands/folder will not hydrate them on the client. - Forgetting to import the island component in your page means no client-side interactivity.
- Using state or event handlers in non-island components will not work because they are server-rendered only.
- Ensure you use hooks like
useStateonly inside island components.
tsx
/// Wrong: Interactive component outside islands folder import { useState } from "preact/hooks"; export default function WrongCounter() { const [count, setCount] = useState(0); return <button onClick={() => setCount(count + 1)}>Count: {count}</button>; } /// Right: Place inside islands folder and import // islands/Counter.tsx as shown in the example // Then import and use in page import Counter from "../islands/Counter.tsx"; export default function Home() { return <Counter />; }
Quick Reference
| Concept | Description |
|---|---|
| Island Component | A client-side interactive component inside the islands/ folder |
| Hydration | Fresh automatically hydrates islands on the client for interactivity |
| Importing | Import islands in your page to use them |
| Server Rendering | Pages are server-rendered except islands which hydrate on client |
| Hooks Usage | Use hooks like useState only inside islands |
Key Takeaways
Place interactive components inside the islands/ folder to enable client-side hydration.
Import island components into your pages to use them and get interactivity.
Only island components support hooks and client-side state; other components are server-rendered.
Fresh automatically hydrates islands, so no extra setup is needed for client interactivity.
Avoid putting interactive logic outside islands to prevent non-working UI.