Skip to content

Instantly share code, notes, and snippets.

@pauleveritt
Created May 5, 2023 17:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pauleveritt/bef52a4f1f7dd9d7d77ed5d53d8d08a3 to your computer and use it in GitHub Desktop.
Save pauleveritt/bef52a4f1f7dd9d7d77ed5d53d8d08a3 to your computer and use it in GitHub Desktop.
Try to get `this` into a layout view.
import type { FunctionComponent, VNode } from "preact";
import { createContext, render as preactRender } from "preact";
import { expect, test } from "vitest";
export type EleventyContext = {
siteTitle: string;
};
const Context = createContext<EleventyContext | null>(null);
export type EleventyComponent<T> = (
this: EleventyContext,
data: T
) => VNode<{}>;
export function createEleventyContextProvider<T>(
Component: FunctionComponent<{ data: T }>
): EleventyComponent<T> {
return function (this: EleventyContext, data: T): VNode<{}> {
return (
<Context.Provider value={this}>
<Component data={data} />
</Context.Provider>
);
};
}
type PageData = {
title: string;
};
const ThisView = ({ data }: { data: PageData }) => {
// I'm struggling to get this: EleventyContext set correctly for both
// typing and the actual this value.
return (
<>
<h1 id="target">{data.title}</h1>
</>
);
};
export const render = createEleventyContextProvider<PageData>(ThisView);
test("should render", () => {
const thisContext: EleventyContext = {
siteTitle: "My Site",
};
const data: PageData = {
title: "Preact Test",
};
// This simulates what 11ty might do....I think.
const view = render.bind(thisContext)(data);
preactRender(view, document.body);
const target = document.getElementById("target");
// The title should be Preact Test
expect(target?.textConten``t).to.equal(data.title);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment