Skip to main content

Jsx

Simple jsx libs.

Import

Deno

import {...} from "https://deno.land/x/nhttp@1.3.26/lib/jsx.ts";

Deno npm

import {...} from "npm:nhttp-land@1.3.26/jsx";

Node / Bun

import {...} from "nhttp-land/jsx";
// or
// const {...} = require("nhttp-land/jsx");

Usage

/** @jsx n */
/** @jsxFrag n.Fragment */

import nhttp from "https://deno.land/x/nhttp@1.3.26/mod.ts";
import {
type FC,
Helmet,
n,
renderToHtml,
} from "https://deno.land/x/nhttp@1.3.26/lib/jsx.ts";

// support for AsyncComponent
const Fetcher: FC = async () => {
try {
const res = await fetch("http://nhttp.deno.dev/");
return <span>Oke, {res.status}</span>;
} catch (err) {
return <span>Noop, {err.message}</span>;
}
};

const Home: FC<{ title: string }> = (props) => {
return (
<>
<Helmet>
<title>{props.title}</title>
</Helmet>
<h1>Home Page</h1>
<Fetcher />
</>
);
};
const app = nhttp();

app.engine(renderToHtml);
// or stream
// app.engine(renderToReadableStream);

app.get("/", () => {
return <Home title="welcome jsx" />;
});

app.listen(8000, () => {
console.log("> Running on port 8000");
});

Config Automatic

Transform to react-jsx

// deno.json
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "nhttp-jsx"
},
"imports": {
"nhttp-jsx/jsx-runtime": "https://deno.land/x/nhttp@1.3.26/lib/jsx/jsx-runtime.ts"
}
}

Transform to Precompile

Deno has claimed 7 ~ 20x faster. ref => fastest jsx transform

// deno.json
{
"compilerOptions": {
"jsx": "precompile",
"jsxImportSource": "nhttp-jsx"
},
"imports": {
"nhttp-jsx/jsx-runtime": "https://deno.land/x/nhttp@1.3.26/lib/jsx/jsx-runtime.ts"
}
}

Using Hooks

useRequestEvent

use requestEvent.

import { useRequestEvent } from "https://deno.land/x/nhttp@1.3.26/lib/jsx.ts";

const Home: FC = () => {
const rev = useRequestEvent();

return <h1>The url is {rev.url}</h1>;
};

useParams

use parameter from router. e.g. /user/:name.

import { useParams } from "https://deno.land/x/nhttp@1.3.26/lib/jsx.ts";

const User: FC = () => {
const params = useParams<{ name: string }>();

return <h1>{params.name}</h1>;
};

useQuery

use query parameter from url. e.g. /user?name=john.

import { useQuery } from "https://deno.land/x/nhttp@1.3.26/lib/jsx.ts";

const User: FC = () => {
const query = useQuery<{ name: string }>();

return <h1>{query.name}</h1>;
};

useBody

use request body.

import { useBody } from "https://deno.land/x/nhttp@1.3.26/lib/jsx.ts";

const User: FC = async () => {
const user = useBody<{ name: string }>();

// example save to db.
await db_user.save(user);

return <h1>{user.name}</h1>;
};

useResponse

use http_response.

import { useResponse } from "https://deno.land/x/nhttp@1.3.26/lib/jsx.ts";

const User: FC = () => {
const res = useResponse();

res.setHeader("name", "john");

return <h1>{res.getHeader("name")}</h1>;
};

useScript

minimal for simple client interactive.

import { useScript } from "https://deno.land/x/nhttp@1.3.26/lib/jsx.ts";

const Counter: FC = () => {
const state = { count: 0 };

useScript(state, (state) => {
const $ = (id: string) => {
const c = document.querySelector("#counter_app");
return c.querySelector(`#${id}`) as HTMLElement;
};

$("plus").onclick = () => {
$("count").innerText = String(state.count += 1);
};

$("min").onclick = () => {
$("count").innerText = String(state.count -= 1);
};
});

return (
<div id="counter_app">
<button id="plus">+ Increment</button>
<h1 id="count">{state.count}</h1>
<button id="min">- Decrement</button>
</div>
);
};

useId

generate unique id.

import { useId } from "https://deno.land/x/nhttp@1.3.26/lib/jsx.ts";

const User: FC = () => {
const title_id = useId();
const label_id = useId();

return (
<>
<h1 id={title_id}>Title</h1>
<label id={label_id}>Label</label>
</>
);
};

useStyle

add style directly to the markup.

import { useStyle } from "https://deno.land/x/nhttp@1.3.26/lib/jsx.ts";

const User: FC = () => {
useStyle({
".title": {
backgroundColor: "red",
},
".label": {
color: "blue",
},
});

return (
<>
<h1 className="title">Title</h1>
<label className="label">Label</label>
</>
);
};

Context

Add context provider.

import {
createContext,
useContext,
} from "https://deno.land/x/nhttp@1.3.26/lib/jsx.ts";

const FooContext = createContext();

const Foo: FC = () => {
const foo = useContext(FooContext);

return <h1>{foo}</h1>;
};

app.get("/foo", () => {
return (
<FooContext.Provider value="foobar">
<Foo />
</FooContext.Provider>
);
});

With Htmx

/** @jsx n */
/** @jsxFrag n.Fragment */
import nhttp from "https://deno.land/x/nhttp@1.3.26/mod.ts";
import { n, htmx, renderToHtml } from "https://deno.land/x/nhttp@1.3.26/lib/jsx.ts";

const app = nhttp();

app.engine(renderToHtml);

app.use(htmx());

app.get("/", () => {
return (
<button hx-post="/clicked" hx-swap="outerHTML">
Click Me
</button>
);
});

app.post("/clicked", () => {
return <span>It's Me</span>;
});

app.listen(8000);

With Twind Server

/** @jsx n */
/** @jsxFrag n.Fragment */

import {
FC,
n,
renderToHtml,
} from "https://deno.land/x/nhttp@1.3.26/lib/jsx.ts";
import { useTwindServer } from "https://deno.land/x/nhttp@1.3.26/lib/jsx/twind-server.ts";
import nhttp from "https://deno.land/x/nhttp@1.3.26/mod.ts";

useTwindServer();

const app = nhttp();

app.engine(renderToHtml);

app.get("/", () => <h1 className="mt-20">hello twind</h1>);

app.listen(8000, () => {
console.log("> Running on port 8000");
});

With React

import React from "https://esm.sh/react";
import {
Helmet,
options,
renderToHtml,
} from "https://deno.land/x/nhttp@1.3.26/lib/jsx.ts";
import { renderToString } from "https://esm.sh/react-dom/server";
import nhttp from "https://deno.land/x/nhttp@1.3.26/mod.ts";

options.onRenderElement = (elem) => {
return renderToString(elem);
};

const app = nhttp();

app.engine(renderToHtml);

app.get("/", () => {
return (
<>
<Helmet>
<title>With React</title>
</Helmet>
<h1>Hello From React</h1>
</>
);
});

app.listen(8000, () => {
console.log("> Running on port 8000");
});

With Preact

/** @jsx h */
/** @jsxFrag Fragment */

import { Fragment, h } from "https://esm.sh/preact";
import {
Helmet,
options,
renderToHtml,
} from "https://deno.land/x/nhttp@1.3.26/lib/jsx.ts";
import { renderToString } from "https://esm.sh/preact-render-to-string";
import nhttp from "https://deno.land/x/nhttp@1.3.26/mod.ts";

options.onRenderElement = (elem) => {
return renderToString(elem);
};

const app = nhttp();

app.engine(renderToHtml);

app.get("/", () => {
return (
<>
<Helmet>
<title>With Preact</title>
</Helmet>
<h1>Hello From Preact</h1>
</>
);
});

app.listen(8000, () => {
console.log("> Running on port 8000");
});