Skip to content

Commit

Permalink
Fix useMemoCache with setState in render
Browse files Browse the repository at this point in the history
Fixes the bug that @alexmckenley and @mofeiZ found where setState-in-render can reset useMemoCache and cause an infinite loop. The bug was that renderWithHooksAgain() was not resetting hook state when rerendering (so useMemo values were preserved) but was resetting the updateQueue. This meant that the entire memo cache was cleared on a setState-in-render.

The fix here is to call a new helper function to clear the update queue. It nulls out other properties, but for memoCache it just sets the index back to zero.

ghstack-source-id: fc0947ce219334117075df6a4e33b39975af2bc4
Pull Request resolved: #30889

DiffTrain build for [727b361](727b361)
  • Loading branch information
josephsavona committed Sep 6, 2024
1 parent 716cd41 commit eb67bf1
Show file tree
Hide file tree
Showing 34 changed files with 1,346 additions and 1,226 deletions.
2 changes: 1 addition & 1 deletion compiled/facebook-www/REVISION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
a03254bc60b06c535c37e43c53b1fd40757b2ef4
727b3615287074ddaa28069bfbd2dfee8cf73575
2 changes: 1 addition & 1 deletion compiled/facebook-www/REVISION_TRANSFORMS
Original file line number Diff line number Diff line change
@@ -1 +1 @@
a03254bc60b06c535c37e43c53b1fd40757b2ef4
727b3615287074ddaa28069bfbd2dfee8cf73575
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -2001,7 +2001,7 @@ __DEV__ &&
exports.useTransition = function () {
return resolveDispatcher().useTransition();
};
exports.version = "19.0.0-www-classic-a03254bc-20240905";
exports.version = "19.0.0-www-classic-727b3615-20240906";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -1981,7 +1981,7 @@ __DEV__ &&
exports.useTransition = function () {
return resolveDispatcher().useTransition();
};
exports.version = "19.0.0-www-modern-a03254bc-20240905";
exports.version = "19.0.0-www-modern-727b3615-20240906";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-prod.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -665,4 +665,4 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.0.0-www-classic-a03254bc-20240905";
exports.version = "19.0.0-www-classic-727b3615-20240906";
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-prod.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -665,4 +665,4 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.0.0-www-modern-a03254bc-20240905";
exports.version = "19.0.0-www-modern-727b3615-20240906";
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-profiling.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,7 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.0.0-www-classic-a03254bc-20240905";
exports.version = "19.0.0-www-classic-727b3615-20240906";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-profiling.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,7 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.0.0-www-modern-a03254bc-20240905";
exports.version = "19.0.0-www-modern-727b3615-20240906";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
38 changes: 22 additions & 16 deletions compiled/facebook-www/ReactART-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -4096,10 +4096,16 @@ __DEV__ &&
numberOfReRenders += 1;
ignorePreviousDependencies = !1;
workInProgressHook = currentHook = null;
workInProgress.updateQueue = null;
if (null != workInProgress.updateQueue) {
var children = workInProgress.updateQueue;
children.lastEffect = null;
children.events = null;
children.stores = null;
null != children.memoCache && (children.memoCache.index = 0);
}
hookTypesUpdateIndexDev = -1;
ReactSharedInternals.H = HooksDispatcherOnRerenderInDEV;
var children = callComponentInDEV(Component, props, secondArg);
children = callComponentInDEV(Component, props, secondArg);
} while (didScheduleRenderPhaseUpdateDuringThisPass);
return children;
}
Expand Down Expand Up @@ -4878,17 +4884,16 @@ __DEV__ &&
function pushEffect(tag, create, inst, deps) {
tag = { tag: tag, create: create, inst: inst, deps: deps, next: null };
create = currentlyRenderingFiber$1.updateQueue;
null === create
? ((create = createFunctionComponentUpdateQueue()),
(currentlyRenderingFiber$1.updateQueue = create),
(create.lastEffect = tag.next = tag))
: ((inst = create.lastEffect),
null === inst
? (create.lastEffect = tag.next = tag)
: ((deps = inst.next),
(inst.next = tag),
(tag.next = deps),
(create.lastEffect = tag)));
null === create &&
((create = createFunctionComponentUpdateQueue()),
(currentlyRenderingFiber$1.updateQueue = create));
inst = create.lastEffect;
null === inst
? (create.lastEffect = tag.next = tag)
: ((deps = inst.next),
(inst.next = tag),
(tag.next = deps),
(create.lastEffect = tag));
return tag;
}
function mountRef(initialValue) {
Expand Down Expand Up @@ -6691,6 +6696,7 @@ __DEV__ &&
hookTypesUpdateIndexDev = -1;
ignorePreviousDependencies =
null !== current && current.type !== workInProgress.type;
workInProgress.updateQueue = null;
nextProps = renderWithHooksAgain(
workInProgress,
Component,
Expand Down Expand Up @@ -16958,11 +16964,11 @@ __DEV__ &&
(function () {
var internals = {
bundleType: 1,
version: "19.0.0-www-classic-a03254bc-20240905",
version: "19.0.0-www-classic-727b3615-20240906",
rendererPackageName: "react-art",
currentDispatcherRef: ReactSharedInternals,
findFiberByHostInstance: getInstanceFromNode,
reconcilerVersion: "19.0.0-www-classic-a03254bc-20240905"
reconcilerVersion: "19.0.0-www-classic-727b3615-20240906"
};
internals.overrideHookState = overrideHookState;
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
Expand Down Expand Up @@ -16996,7 +17002,7 @@ __DEV__ &&
exports.Shape = Shape;
exports.Surface = Surface;
exports.Text = Text;
exports.version = "19.0.0-www-classic-a03254bc-20240905";
exports.version = "19.0.0-www-classic-727b3615-20240906";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
38 changes: 22 additions & 16 deletions compiled/facebook-www/ReactART-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -3972,10 +3972,16 @@ __DEV__ &&
numberOfReRenders += 1;
ignorePreviousDependencies = !1;
workInProgressHook = currentHook = null;
workInProgress.updateQueue = null;
if (null != workInProgress.updateQueue) {
var children = workInProgress.updateQueue;
children.lastEffect = null;
children.events = null;
children.stores = null;
null != children.memoCache && (children.memoCache.index = 0);
}
hookTypesUpdateIndexDev = -1;
ReactSharedInternals.H = HooksDispatcherOnRerenderInDEV;
var children = callComponentInDEV(Component, props, secondArg);
children = callComponentInDEV(Component, props, secondArg);
} while (didScheduleRenderPhaseUpdateDuringThisPass);
return children;
}
Expand Down Expand Up @@ -4754,17 +4760,16 @@ __DEV__ &&
function pushEffect(tag, create, inst, deps) {
tag = { tag: tag, create: create, inst: inst, deps: deps, next: null };
create = currentlyRenderingFiber$1.updateQueue;
null === create
? ((create = createFunctionComponentUpdateQueue()),
(currentlyRenderingFiber$1.updateQueue = create),
(create.lastEffect = tag.next = tag))
: ((inst = create.lastEffect),
null === inst
? (create.lastEffect = tag.next = tag)
: ((deps = inst.next),
(inst.next = tag),
(tag.next = deps),
(create.lastEffect = tag)));
null === create &&
((create = createFunctionComponentUpdateQueue()),
(currentlyRenderingFiber$1.updateQueue = create));
inst = create.lastEffect;
null === inst
? (create.lastEffect = tag.next = tag)
: ((deps = inst.next),
(inst.next = tag),
(tag.next = deps),
(create.lastEffect = tag));
return tag;
}
function mountRef(initialValue) {
Expand Down Expand Up @@ -6203,6 +6208,7 @@ __DEV__ &&
hookTypesUpdateIndexDev = -1;
ignorePreviousDependencies =
null !== current && current.type !== workInProgress.type;
workInProgress.updateQueue = null;
nextProps = renderWithHooksAgain(
workInProgress,
Component,
Expand Down Expand Up @@ -16404,11 +16410,11 @@ __DEV__ &&
(function () {
var internals = {
bundleType: 1,
version: "19.0.0-www-modern-a03254bc-20240905",
version: "19.0.0-www-modern-727b3615-20240906",
rendererPackageName: "react-art",
currentDispatcherRef: ReactSharedInternals,
findFiberByHostInstance: getInstanceFromNode,
reconcilerVersion: "19.0.0-www-modern-a03254bc-20240905"
reconcilerVersion: "19.0.0-www-modern-727b3615-20240906"
};
internals.overrideHookState = overrideHookState;
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
Expand Down Expand Up @@ -16442,7 +16448,7 @@ __DEV__ &&
exports.Shape = Shape;
exports.Surface = Surface;
exports.Text = Text;
exports.version = "19.0.0-www-modern-a03254bc-20240905";
exports.version = "19.0.0-www-modern-727b3615-20240906";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
52 changes: 29 additions & 23 deletions compiled/facebook-www/ReactART-prod.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -2593,9 +2593,15 @@ function renderWithHooksAgain(workInProgress, Component, props, secondArg) {
if (25 <= numberOfReRenders) throw Error(formatProdErrorMessage(301));
numberOfReRenders += 1;
workInProgressHook = currentHook = null;
workInProgress.updateQueue = null;
if (null != workInProgress.updateQueue) {
var children = workInProgress.updateQueue;
children.lastEffect = null;
children.events = null;
children.stores = null;
null != children.memoCache && (children.memoCache.index = 0);
}
ReactSharedInternals.H = HooksDispatcherOnRerender;
var children = Component(props, secondArg);
children = Component(props, secondArg);
} while (didScheduleRenderPhaseUpdateDuringThisPass);
return children;
}
Expand Down Expand Up @@ -3203,17 +3209,16 @@ function rerenderActionState(action) {
function pushEffect(tag, create, inst, deps) {
tag = { tag: tag, create: create, inst: inst, deps: deps, next: null };
create = currentlyRenderingFiber$1.updateQueue;
null === create
? ((create = createFunctionComponentUpdateQueue()),
(currentlyRenderingFiber$1.updateQueue = create),
(create.lastEffect = tag.next = tag))
: ((inst = create.lastEffect),
null === inst
? (create.lastEffect = tag.next = tag)
: ((deps = inst.next),
(inst.next = tag),
(tag.next = deps),
(create.lastEffect = tag)));
null === create &&
((create = createFunctionComponentUpdateQueue()),
(currentlyRenderingFiber$1.updateQueue = create));
inst = create.lastEffect;
null === inst
? (create.lastEffect = tag.next = tag)
: ((deps = inst.next),
(inst.next = tag),
(tag.next = deps),
(create.lastEffect = tag));
return tag;
}
function updateRef() {
Expand Down Expand Up @@ -4683,6 +4688,7 @@ function replayFunctionComponent(
renderLanes
) {
prepareToReadContext(workInProgress);
workInProgress.updateQueue = null;
nextProps = renderWithHooksAgain(
workInProgress,
Component,
Expand Down Expand Up @@ -10773,27 +10779,27 @@ var slice = Array.prototype.slice,
};
return Text;
})(React.Component);
var internals$jscomp$inline_1420 = {
var internals$jscomp$inline_1422 = {
bundleType: 0,
version: "19.0.0-www-classic-a03254bc-20240905",
version: "19.0.0-www-classic-727b3615-20240906",
rendererPackageName: "react-art",
currentDispatcherRef: ReactSharedInternals,
findFiberByHostInstance: function () {
return null;
},
reconcilerVersion: "19.0.0-www-classic-a03254bc-20240905"
reconcilerVersion: "19.0.0-www-classic-727b3615-20240906"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1421 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
var hook$jscomp$inline_1423 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
if (
!hook$jscomp$inline_1421.isDisabled &&
hook$jscomp$inline_1421.supportsFiber
!hook$jscomp$inline_1423.isDisabled &&
hook$jscomp$inline_1423.supportsFiber
)
try {
(rendererID = hook$jscomp$inline_1421.inject(
internals$jscomp$inline_1420
(rendererID = hook$jscomp$inline_1423.inject(
internals$jscomp$inline_1422
)),
(injectedHook = hook$jscomp$inline_1421);
(injectedHook = hook$jscomp$inline_1423);
} catch (err) {}
}
var Path = Mode$1.Path;
Expand All @@ -10807,4 +10813,4 @@ exports.RadialGradient = RadialGradient;
exports.Shape = TYPES.SHAPE;
exports.Surface = Surface;
exports.Text = Text;
exports.version = "19.0.0-www-classic-a03254bc-20240905";
exports.version = "19.0.0-www-classic-727b3615-20240906";
Loading

0 comments on commit eb67bf1

Please sign in to comment.