|
1 | 1 | import { signal, computed, effect, batch, Signal } from "@preact/signals-core";
|
| 2 | +import fastEqual from "fast-deep-equal/es6"; |
2 | 3 |
|
3 | 4 | describe("signal", () => {
|
4 | 5 | it("should return value", () => {
|
@@ -1711,4 +1712,47 @@ describe("batch/transaction", () => {
|
1711 | 1712 | });
|
1712 | 1713 | expect(callCount).to.equal(1);
|
1713 | 1714 | });
|
| 1715 | + |
| 1716 | + it("allows customizing the default shouldUpdate compare method", () => { |
| 1717 | + const mapA = new Map<string, string>(); |
| 1718 | + const a = signal(mapA); |
| 1719 | + const spy1 = sinon.spy(() => a.value); |
| 1720 | + effect(spy1); |
| 1721 | + |
| 1722 | + // before: re-renders every time, even if the value doesn't change |
| 1723 | + a.value = new Map(a.peek()).set("foo", "bar"); |
| 1724 | + a.value = new Map(a.peek()).set("foo", "baz"); |
| 1725 | + a.value = new Map(a.peek()).set("foo", "baz"); |
| 1726 | + a.value = new Map(a.peek()).set("foo", "baz"); |
| 1727 | + |
| 1728 | + // should have been called twice but instead re-renders regardless on value pass in (without specifying a custom shouldUpdate method) |
| 1729 | + expect(spy1.callCount).to.equal(5); |
| 1730 | + |
| 1731 | + Signal.prototype.shouldUpdate = (oldValue, newValue) => { |
| 1732 | + if (oldValue instanceof Map && newValue instanceof Map) { |
| 1733 | + return fastEqual(oldValue, newValue) === false; |
| 1734 | + } |
| 1735 | + return oldValue !== newValue; |
| 1736 | + }; |
| 1737 | + |
| 1738 | + function signal2<T>(value: T): Signal<T> { |
| 1739 | + return new Signal(value); |
| 1740 | + } |
| 1741 | + |
| 1742 | + const mapB = new Map<string, string>(); |
| 1743 | + const b = signal2(mapB); |
| 1744 | + const spy2 = sinon.spy(() => b.value); |
| 1745 | + effect(spy2); |
| 1746 | + |
| 1747 | + // after: only re-renders if the value changes (via custom shouldUpdate method) |
| 1748 | + b.value = new Map(b.peek()).set("foo", "bar"); |
| 1749 | + b.value = new Map(b.peek()).set("foo", "baz"); |
| 1750 | + b.value = new Map(b.peek()).set("foo", "baz"); |
| 1751 | + b.value = new Map(b.peek()).set("foo", "baz"); |
| 1752 | + |
| 1753 | + // setting up the initial empty Map --> update #1 |
| 1754 | + // adding foo, bar to empty map --> update #2 |
| 1755 | + // updating foo, bar to foo, baz --> update #3 |
| 1756 | + expect(spy2.callCount).to.equal(3); |
| 1757 | + }); |
1714 | 1758 | });
|
0 commit comments