Skip to content

Commit

Permalink
Backport state settling (#641)
Browse files Browse the repository at this point in the history
  • Loading branch information
JoviDeCroock authored Jan 10, 2025
1 parent d4ff246 commit e932cfc
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 7 deletions.
5 changes: 5 additions & 0 deletions .changeset/silver-crabs-sniff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@preact/signals": patch
---

Change the way we deal with state settling hooks, when we know we are dealing with hooks that can settle their A -> B -> A state (and wind up at the same value). We should not verbatim rerender in our custom shouldComponentUpdate. Instead we should trust that hooks have handled their own state settling.
25 changes: 18 additions & 7 deletions packages/preact/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,16 +328,27 @@ Component.prototype.shouldComponentUpdate = function (
// });
// }

// if this component used no signals or computeds, update:
if (!hasSignals && !(this._updateFlags & HAS_COMPUTEDS)) return true;

// if there is a pending re-render triggered from Signals,
// or if there is hook or class state, update:
if (this._updateFlags & (HAS_PENDING_UPDATE | HAS_HOOK_STATE)) return true;

// @ts-ignore
for (let i in state) return true;

if (this.__f || (typeof this.u == "boolean" && this.u === true)) {
const hasHooksState = this._updateFlags & HAS_HOOK_STATE;
// if this component used no signals or computeds and no hooks state, update:
if (!hasSignals && !hasHooksState && !(this._updateFlags & HAS_COMPUTEDS))
return true;

// if there is a pending re-render triggered from Signals,
// or if there is hooks state, update:
if (this._updateFlags & HAS_PENDING_UPDATE) return true;
} else {
// if this component used no signals or computeds, update:
if (!hasSignals && !(this._updateFlags & HAS_COMPUTEDS)) return true;

// if there is a pending re-render triggered from Signals,
// or if there is hooks state, update:
if (this._updateFlags & (HAS_PENDING_UPDATE | HAS_HOOK_STATE)) return true;
}

// if any non-Signal props changed, update:
for (let i in props) {
if (i !== "__source" && props[i] !== this.props[i]) return true;
Expand Down
5 changes: 5 additions & 0 deletions packages/preact/src/internal.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ export interface AugmentedElement extends HTMLElement {
}

export interface AugmentedComponent extends Component<any, any> {
// hasScuFromHooks
// Preact 10.12 - Preact 10.25
u?: boolean;
// Preact 10.26 and onwards
__f?: boolean;
__v: VNode;
_updater?: Effect;
_updateFlags: number;
Expand Down

0 comments on commit e932cfc

Please sign in to comment.