Skip to content

Commit

Permalink
Adds custom-hook demo.
Browse files Browse the repository at this point in the history
  • Loading branch information
dgp1130 committed Dec 28, 2023
1 parent 35813da commit 48fc554
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/demo/hooks/custom-hook.test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<title>`custom-hook` tests</title>
<meta charset="utf8">
</head>
<body></body>
</html>
70 changes: 70 additions & 0 deletions src/demo/hooks/custom-hook.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { parseHtml } from 'hydroactive/testing.js';
import { CustomHook } from './custom-hook.js';

describe('custom-hook', () => {
beforeEach(() => { jasmine.clock().install(); });
afterEach(() => { jasmine.clock().uninstall(); });

afterEach(() => {
for (const node of document.body.childNodes) node.remove();
});

function render({ count }: { count: number }) {
return parseHtml(CustomHook, `
<custom-hook>
<div>The current count is: <span>${count}</span>.</div>
</custom-hook>
`);
}

describe('CustomHook', () => {
it('does not re-render on hydration', async () => {
const el = render({ count: 5 });
document.body.appendChild(el);

await el.stable();

expect(el.querySelector('span')!.textContent).toBe('5');
});

it('updates the count every second', async () => {
const el = render({ count: 5 });
document.body.appendChild(el);

jasmine.clock().tick(1_000);
await el.stable();

expect(el.querySelector('span')!.textContent).toBe('6');
});

it('pauses the count while disconnected', async () => {
const el = render({ count: 5 });

document.body.appendChild(el);
el.remove(); // Should pause timer.

jasmine.clock().tick(1_000);
await el.stable();

// Should not have incremented.
expect(el.querySelector('span')!.textContent).toBe('5');
});

it('resumes the count when reconnected', async () => {
const el = render({ count: 5 });

document.body.appendChild(el);
el.remove(); // Should pause timer.

jasmine.clock().tick(3_000);

document.body.appendChild(el); // Should resume timer.

jasmine.clock().tick(1_000);
await el.stable();

// Should have incremented only once.
expect(el.querySelector('span')!.textContent).toBe('6');
});
});
});
42 changes: 42 additions & 0 deletions src/demo/hooks/custom-hook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { ComponentRef, defineComponent } from 'hydroactive';
import { Signal, signal } from 'hydroactive/signals.js';

/** Demonstrates a custom hook for controlling the count timer. */
export const CustomHook = defineComponent('custom-hook', (comp) => {
const initial = comp.host.query('span').read(Number);

// Create a signal which is automatically incremented every second. Bound to
// the component's lifecycle.
const count = useTimer(comp, initial);

comp.bind('span', () => count());
});

declare global {
interface HTMLElementTagNameMap {
'custom-hook': InstanceType<typeof CustomHook>;
}
}

/**
* Custom "hook" to automatically increment a signal. Can be reused across
* multiple components. The only trick here is accepting `comp` as an input
* parameter so it can tie into the component's lifecycle appropriately.
*/
function useTimer(comp: ComponentRef, initial: number): Signal<number> {
const count = signal(initial);

comp.connected(() => {
const handle = setInterval(() => {
count.set(count() + 1);
}, 1_000);

return () => {
clearInterval(handle);
};
});

// Use `.readonly` to convert the `WriteableSignal` into a readonly `Signal`.
// This prevents anyone from accidentally calling `set` on the return value.
return count.readonly();
}
29 changes: 29 additions & 0 deletions src/demo/hooks/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<title>Hooks Demo</title>
<meta charset="utf8">

<script type="importmap">
{
"imports": {
"hydroactive": "/hydroactive/index.js",
"hydroactive/": "/hydroactive/"
}
}
</script>
</head>
<body>
<h1>Hooks Demo</h1>

<nav><a href="/">Home</a></nav>

<custom-hook>
<h2>Custom Hook</h2>

<div>The current count is: <span id="count">5</span>.</div>

<script src="./custom-hook.js" type="module"></script>
</custom-hook>
</body>
</html>
1 change: 1 addition & 0 deletions src/demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ <h1>HydroActive Demo</h1>
<li><a href="/counter/">Counter</a></li>
<li><a href="/attrs/">Attributes</a></li>
<li><a href="/reactivity/">Reactivity</a></li>
<li><a href="/hooks/">Hooks</a></li>
</ul>
</nav>
</body>
Expand Down

0 comments on commit 48fc554

Please sign in to comment.