diff --git a/.changeset/ninety-beans-compare.md b/.changeset/ninety-beans-compare.md index de5b0a0f..fd3e8b1a 100644 --- a/.changeset/ninety-beans-compare.md +++ b/.changeset/ninety-beans-compare.md @@ -2,4 +2,15 @@ "@preact/signals": minor --- -Defer all DOM updates by an animation frame as well +Defer all DOM updates by an animation frame, this should make it so +that any used to be synchronous DOM update will be delayed by an +animation frame. This allows Preact to first perform its own render +cycle and then our direct DOM updates to occur. These will now +be performed in a batched way which is more performant as the browser +is prepared to handle these during the animation frame. + +This does have one way to how Preact based signals are tested, when +we perform a signal update we have to wrap it in `act`, in a way +this was always the case as a signal update that resulted in +a Preact state update would require it to be wrapped in `act` but +now this is the norm. diff --git a/packages/preact/src/index.ts b/packages/preact/src/index.ts index 02f3e832..7a408d6b 100644 --- a/packages/preact/src/index.ts +++ b/packages/preact/src/index.ts @@ -381,7 +381,7 @@ function flushEffects() { function notifyEffects(this: Effect) { if (effectsQueue.push(this) === 1) { - (options.debounceRendering || defer)(flushEffects); + (options.requestAnimationFrame || defer)(flushEffects); } } @@ -394,7 +394,7 @@ function flushComputeds() { function notifyComputeds(this: Effect) { if (computedsQueue.push(this) === 1) { - (options.debounceRendering || defer)(flushComputeds); + (options.requestAnimationFrame || defer)(flushComputeds); } } diff --git a/packages/preact/test/index.test.tsx b/packages/preact/test/index.test.tsx index ff85d85c..a74ca53b 100644 --- a/packages/preact/test/index.test.tsx +++ b/packages/preact/test/index.test.tsx @@ -13,17 +13,8 @@ import { useContext, useRef, useState } from "preact/hooks"; import { setupRerender, act } from "preact/test-utils"; const sleep = (ms?: number) => new Promise(r => setTimeout(r, ms)); -const defer = - typeof requestAnimationFrame === "undefined" - ? setTimeout - : requestAnimationFrame; -const afterFrame = () => { - return new Promise(res => { - defer(res); - }); -}; -describe.only("@preact/signals", () => { +describe("@preact/signals", () => { let scratch: HTMLDivElement; let rerender: () => void; @@ -234,7 +225,6 @@ describe.only("@preact/signals", () => { act(() => { sig.value = d; }); - await afterFrame(); rerender(); await sleep(); @@ -707,7 +697,6 @@ describe.only("@preact/signals", () => { }); expect(scratch.textContent).to.equal("foo"); // expect(spy).not.to.have.been.called; - await afterFrame(); expect(spy).to.have.been.calledOnceWith( "foo", scratch.firstElementChild, @@ -756,7 +745,6 @@ describe.only("@preact/signals", () => { render(, scratch); }); - await afterFrame(); expect(cleanup).not.to.have.been.called; expect(spy).to.have.been.calledOnceWith( "foo", diff --git a/packages/react/test/shared/updates.tsx b/packages/react/test/shared/updates.tsx index 03b863ba..64f73847 100644 --- a/packages/react/test/shared/updates.tsx +++ b/packages/react/test/shared/updates.tsx @@ -170,7 +170,6 @@ export function updateSignalsTests(usingTransform = false) { await act(() => { sig.value = "bar"; }); - await afterFrame(); expect(scratch.textContent).to.equal("bar"); }); @@ -292,7 +291,6 @@ export function updateSignalsTests(usingTransform = false) { await act(() => { sig.value = "bar"; }); - await afterFrame(); expect(scratch.textContent).to.equal("bar"); }); @@ -313,7 +311,6 @@ export function updateSignalsTests(usingTransform = false) { await act(() => { sig.value = "bar"; }); - await afterFrame(); expect(scratch.textContent).to.equal("bar"); }); @@ -334,7 +331,6 @@ export function updateSignalsTests(usingTransform = false) { await act(async () => { sig.value = i; }); - await afterFrame(); expect(scratch.textContent).to.equal("" + i); } }); @@ -356,7 +352,6 @@ export function updateSignalsTests(usingTransform = false) { await act(async () => { sig.value = i; }); - await afterFrame(); expect(scratch.textContent).to.equal("" + i); } }); @@ -425,7 +420,6 @@ export function updateSignalsTests(usingTransform = false) { await act(async () => { count.value += 1; }); - await afterFrame(); expect(scratch.innerHTML).to.equal( `
-2${count.value * 2}
` ); @@ -632,7 +626,6 @@ export function updateSignalsTests(usingTransform = false) { await act(() => { scratch.querySelector("button")!.click(); }); - await afterFrame(); expect(url.textContent).to.equal("https://domain.com/test?a=2"); expect(URLModelProvider).to.be.calledOnce;