Skip to main content
Deno 2 is finally here šŸŽ‰ļø
Learn more

deno.land/x/preact

This module re-exports the latest version of Preact for the Deno ecosystem. The preact module and its hooks sub-module are combined into a single mod.ts. The @jsxImportSource pragma is supported.

/** @jsxImportSource https://deno.land/x/preact */
import { useState, render } from "https://deno.land/x/preact/mod.ts";

export function App() {
  const [clicks, setClicks] = useState(0);

  return (
    <main>
      <h1>Click count: {clicks}</h1>
      <button onClick={() => setClicks(clicks + 1)}>Click me</button>
    </main>
  );
}

render(<App />, document.body);

Note from the maintainer

I am not a Preact maintainer or contributor. I wanted a version of Preact hosted on deno.land/x and when I checked, the preact module name was still available. I intend to keep this module up-to-date with the latest Preact release. Iā€™ve also added a couple simple utilities that I think other Preact developers might benefit from.

If your name is Jason Miller and youā€™re the Jason Miller who holds Preactā€™s copyright, hmu on twitter if you want to take ownership of deno.land/x/preact. Iā€™ll gladly hand it over if you want it, I can move the extra stuff to a different module.

<shadow-root>

NOTE: This is not part of the standard Preact API

In addition to exporting Preact, this module also registers and exports the <shadow-root> custom element.

<shadow-root> simply slots its content into a ShadowRoot, providing a quick and easy way to achieve scoped CSS in your Preact components.

/** @jsxImportSource https://deno.land/x/preact */
import { render } from "https://deno.land/x/preact";

export function App1() {
  return <shadow-root type="app1">
    {/* The `type="app1"` above has no effect, it's only for show */}
    <h1>App1</h1>

    <style>{`
      /* This style will be applied to the shadow-root element itself */
      :host {
        margin-bottom: 1em;
      }

      /* This style will only be applied to the <h1>App1</h1> above */
      h1 {
        color: red;
      }
    `}</style>
  </shadow-root>;
}

export function App2() {
  return <shadow-root type="app2">
    <h1>App2</h1>

    {/* Externally linked styles are supported */}
    {/* Contents of blue-heading.css: `h1 { color: blue }` */}
    <link rel="stylesheet" href="/blue-heading.css" />
  </shadow-root>;
}

// Red "App1" followed horizontally by a blue "App2" with some space between
render(<>
  <App1 />
  <App2 />
</>, document.body);

The <shadow-root> custom element class is very simple. See extras.ts for details. Also, note that ShadowRoots do more than just style scoping. Read the docs for more information on their implications.

If you want CSS syntax highlighting inside the scoped <style>s, have a look at the styled-jsx extension for Visual Studio Code.

Hereā€™s the caniuse for the ShadowRoot API.

cx()

NOTE: This is not part of the standard Preact API

A common pattern in the P/react ecosystem is joining class names declaratively with a cx() utility function. This module also comes with a very simple cx() that enables the following:

import { cx } from "https://deno.land/x/preact/mod.ts";

function App() {
  const [ego, setEgo] = useState(0);

  return (
    <button
      class={cx(
        "button",
        ego <= 5 && "font-xs",
        ego > 5 && ego <= 10  && "font-sm",
        ego > 10 && ego <= 15 && "font-md",
        ego > 15 && ego <= 20 && "font-lg",
        ego > 20 && "font-xl",
      )}
      onClick={() => setEgo(ego + 1)}
    >
      {ego <= 20 && `Inflate my ego: ${ego}`}
      {ego > 20 && "I am God."}
    </button>
  );
}

Hereā€™s the definition:

export function cx(...classes: unknown[]): string {
  return classes.filter(c => !!c && typeof c === "string").join(" ");
}