diff --git a/src/crank.ts b/src/crank.ts index 5a1cc217..759d7be6 100644 --- a/src/crank.ts +++ b/src/crank.ts @@ -981,23 +981,11 @@ function diffChildren( } } - const ref = child.ref; if (isPromiseLike(value)) { isAsync = true; - if (typeof ref === "function") { - value = value.then((value) => { - ref(renderer.read(value)); - return value; - }); - } - if (hydrationData !== undefined) { hydrationBlock = value; } - } else { - if (typeof ref === "function") { - ref(renderer.read(value)); - } } } else { // child is a string or undefined @@ -1119,6 +1107,9 @@ function updateRaw( const props = ret.el.props; if (!oldProps || oldProps.value !== props.value) { ret.value = renderer.raw(props.value as any, scope, hydrationData); + if (typeof ret.el.ref === "function") { + ret.el.ref(ret.value); + } } return ret.value; @@ -1231,6 +1222,9 @@ function commitHost( if (value == null) { // This assumes that renderer.create does not return nullish values. value = ret.value = renderer.create(tag, props, scope); + if (typeof ret.el.ref === "function") { + ret.el.ref(value); + } } for (const propName in {...oldProps, ...props}) { diff --git a/test/copy.tsx b/test/copy.tsx index 4c521d2c..5c6cc07f 100644 --- a/test/copy.tsx +++ b/test/copy.tsx @@ -1,6 +1,5 @@ import {suite} from "uvu"; import * as Assert from "uvu/assert"; -import * as Sinon from "sinon"; import {Context, Copy, createElement, Element, Fragment} from "../src/crank.js"; import {renderer} from "../src/dom.js"; @@ -346,25 +345,4 @@ test("copy async generator siblings with refresh", async () => { Assert.is(document.body.innerHTML, "
00
"); }); -test("refs", () => { - renderer.render(
Hello
, document.body); - const mock = Sinon.fake(); - renderer.render(, document.body); - Assert.is(mock.lastCall.args[0], document.body.firstChild); -}); - -test("async refs", async () => { - async function Component() { - await new Promise((resolve) => setTimeout(resolve)); - return Hello; - } - - const p = renderer.render(, document.body); - const mock = Sinon.fake(); - renderer.render(, document.body); - Assert.is(mock.callCount, 0); - await p; - Assert.is(mock.lastCall.args[0], document.body.firstChild); -}); - test.run(); diff --git a/test/refs.tsx b/test/refs.tsx index 73cdc6f0..fa1530aa 100644 --- a/test/refs.tsx +++ b/test/refs.tsx @@ -4,14 +4,7 @@ import * as Sinon from "sinon"; const test = suite("refs"); -import { - Children, - Context, - createElement, - Element, - Fragment, - Raw, -} from "../src/crank.js"; +import {Children, Context, createElement, Element, Raw} from "../src/crank.js"; import {renderer} from "../src/dom.js"; test.after.each(() => { @@ -28,42 +21,27 @@ test("basic", () => { Assert.is(fn.lastCall.args[0], document.body.firstChild); }); -test("child", () => { +test("runs once", () => { const fn = Sinon.fake(); - renderer.render( -
- Hello -
, - document.body, - ); - - Assert.is(document.body.innerHTML, "
Hello
"); + renderer.render(
Hello
, document.body); + renderer.render(
Hello
, document.body); + Assert.is(document.body.innerHTML, "
Hello
"); Assert.is(fn.callCount, 1); - Assert.is(fn.lastCall.args[0], document.body.firstChild!.firstChild); + Assert.is(fn.lastCall.args[0], document.body.firstChild); }); -test("Fragment element", () => { +test("child", () => { const fn = Sinon.fake(); renderer.render(
- - 1 - 2 - 3 - + Hello
, document.body, ); - Assert.is( - document.body.innerHTML, - "
123
", - ); + Assert.is(document.body.innerHTML, "
Hello
"); Assert.is(fn.callCount, 1); - Assert.equal( - fn.lastCall.args[0], - Array.from(document.body.firstChild!.childNodes), - ); + Assert.is(fn.lastCall.args[0], document.body.firstChild!.firstChild); }); test("Raw element", () => { @@ -80,10 +58,10 @@ test("Raw element", () => { Assert.ok(refArgs[0] instanceof Node); }); -test("function component", () => { +test("function component ref passing", () => { const fn = Sinon.fake(); - function Component(): Element { - return Hello; + function Component({ref}: {ref: unknown}): Element { + return Hello; } renderer.render( @@ -98,11 +76,11 @@ test("function component", () => { Assert.is(fn.lastCall.args[0], document.body.firstChild!.firstChild); }); -test("generator component", () => { +test("generator component ref passing", () => { const fn = Sinon.fake(); - function* Component(): Generator { + function* Component({ref}: {ref: unknown}): Generator { while (true) { - yield Hello; + yield Hello; } } @@ -118,10 +96,10 @@ test("generator component", () => { Assert.is(fn.lastCall.args[0], document.body.firstChild!.firstChild); }); -test("async function component", async () => { +test("async function component ref passing", async () => { const fn = Sinon.fake(); - async function Component(): Promise { - return Hello; + async function Component({ref}: {ref: unknown}): Promise { + return Hello; } await renderer.render( @@ -138,9 +116,12 @@ test("async function component", async () => { test("async generator component", async () => { const fn = Sinon.fake(); - async function* Component(this: Context): AsyncGenerator { - for await (const _ of this) { - yield Hello; + async function* Component( + this: Context, + {ref}: {ref: unknown}, + ): AsyncGenerator { + for await ({ref} of this) { + yield Hello; } }