From 8d228d2f6616b2b9d9795b471c296c6bf6388714 Mon Sep 17 00:00:00 2001 From: Jovi De Croock Date: Wed, 22 May 2024 20:45:53 +0200 Subject: [PATCH] create hot path for unmounting a tree of context (#4396) --- src/create-context.js | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/src/create-context.js b/src/create-context.js index 57508fe3cd..190797b595 100644 --- a/src/create-context.js +++ b/src/create-context.js @@ -18,29 +18,19 @@ export function createContext(defaultValue, contextId) { /** @type {FunctionComponent} */ Provider(props) { if (!this.getChildContext) { - /** @type {Component[]} */ + /** @type {Component[] | null} */ let subs = []; let ctx = {}; ctx[contextId] = this; this.getChildContext = () => ctx; + this.componentWillUnmount = () => { + subs = null; + }; + this.shouldComponentUpdate = function (_props) { if (this.props.value !== _props.value) { - // I think the forced value propagation here was only needed when `options.debounceRendering` was being bypassed: - // https://github.com/preactjs/preact/commit/4d339fb803bea09e9f198abf38ca1bf8ea4b7771#diff-54682ce380935a717e41b8bfc54737f6R358 - // In those cases though, even with the value corrected, we're double-rendering all nodes. - // It might be better to just tell folks not to use force-sync mode. - // Currently, using `useContext()` in a class component will overwrite its `this.context` value. - // subs.some(c => { - // c.context = _props.value; - // enqueueRender(c); - // }); - - // subs.some(c => { - // c.context[contextId] = _props.value; - // enqueueRender(c); - // }); subs.some(c => { c._force = true; enqueueRender(c); @@ -52,7 +42,9 @@ export function createContext(defaultValue, contextId) { subs.push(c); let old = c.componentWillUnmount; c.componentWillUnmount = () => { - subs.splice(subs.indexOf(c), 1); + if (subs) { + subs.splice(subs.indexOf(c), 1); + } if (old) old.call(c); }; };