Skip to content

Fix useMemoCache with setState in render #30889

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Sep 6, 2024

Conversation

josephsavona
Copy link
Member

@josephsavona josephsavona commented Sep 5, 2024

Stack from ghstack (oldest at bottom):

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.

I initially changed renderWithHooksAgain() to just reset the updateQueue, nulling out properties and setting the memoCache.index back to 0, but not clearing memoCache.data. That fixed the uMC bug, but caused some tests to fail where effect cleanup wasn’t running when a component was in a tree that suspended and showed a fallback.

Turns out renderWithHooksAgain() is also used to re-render suspended components, and that case depends on the updateQueue being cleared for effects to work correctly. So i updated to clear the updateQueue for the suspense case, reset in the setState-in-render case, and everything works. The result feels pretty clean.

In a follow-up we should be able to avoid resetting the memo cache in the replay case as well. There are a few spots in the codebase where we check for updateQueue === null, and only do processing in that case — including some code related to effect cleanup. I think the right thing to do there would be to check for e.g. updateQueue?.lastEffect == null (and any other relevant properties from updateQueue), and then it would be safe to always reset the updateQueue instead of clearing it.

Copy link

vercel bot commented Sep 5, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
react-compiler-playground ✅ Ready (Inspect) Visit Preview 💬 Add feedback Sep 6, 2024 9:13pm

josephsavona added a commit that referenced this pull request Sep 5, 2024
ghstack-source-id: b3e3b82
Pull Request resolved: #30889
@facebook-github-bot facebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Sep 5, 2024
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-poisoned]
@react-sizebot
Copy link

react-sizebot commented Sep 5, 2024

Comparing: bd788b4...7de65dd

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.js = 6.68 kB 6.68 kB = 1.83 kB 1.82 kB
oss-stable/react-dom/cjs/react-dom-client.production.js = 505.04 kB 503.41 kB = 90.26 kB 90.27 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 6.69 kB 6.69 kB = 1.83 kB 1.83 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js = 512.23 kB 510.62 kB = 91.47 kB 91.45 kB
facebook-www/ReactDOM-prod.classic.js = 600.56 kB 598.74 kB = 106.23 kB 106.09 kB
facebook-www/ReactDOM-prod.modern.js = 576.85 kB 575.03 kB = 102.37 kB 102.27 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
facebook-www/ReactDOM-profiling.classic.js = 630.15 kB 628.77 kB = 110.69 kB 110.55 kB
react-native/implementations/ReactNativeRenderer-profiling.js = 385.95 kB 385.09 kB = 67.08 kB 66.99 kB
facebook-www/ReactDOM-profiling.modern.js = 605.80 kB 604.42 kB = 106.69 kB 106.58 kB
react-native/implementations/ReactNativeRenderer-dev.js = 641.37 kB 639.90 kB = 105.49 kB 105.26 kB
oss-stable/react-reconciler/cjs/react-reconciler.production.js = 380.64 kB 379.62 kB +0.03% 62.39 kB 62.41 kB
oss-stable-rc/react-reconciler/cjs/react-reconciler.production.js = 380.62 kB 379.60 kB +0.03% 62.37 kB 62.39 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.production.js = 380.62 kB 379.60 kB +0.03% 62.37 kB 62.39 kB
react-native/implementations/ReactNativeRenderer-dev.fb.js = 664.72 kB 662.87 kB = 109.16 kB 108.90 kB
react-native/implementations/ReactNativeRenderer-profiling.fb.js = 410.06 kB 408.92 kB = 71.23 kB 71.12 kB
oss-stable/react-dom/cjs/react-dom-profiling.development.js = 952.40 kB 949.71 kB = 161.30 kB 161.14 kB
oss-stable-rc/react-dom/cjs/react-dom-profiling.development.js = 952.30 kB 949.60 kB = 161.27 kB 161.11 kB
oss-stable-semver/react-dom/cjs/react-dom-profiling.development.js = 952.30 kB 949.60 kB = 161.27 kB 161.11 kB
react-native/implementations/ReactFabric-prod.fb.js = 377.24 kB 376.17 kB = 65.82 kB 65.71 kB
react-native/implementations/ReactFabric-prod.js = 349.50 kB 348.51 kB = 61.24 kB 61.14 kB
oss-stable/react-dom/cjs/react-dom-client.development.js = 935.96 kB 933.27 kB = 158.46 kB 158.32 kB
oss-stable-rc/react-dom/cjs/react-dom-client.development.js = 935.86 kB 933.16 kB = 158.43 kB 158.29 kB
oss-stable-semver/react-dom/cjs/react-dom-client.development.js = 935.86 kB 933.16 kB = 158.43 kB 158.29 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.development.js = 966.92 kB 964.09 kB = 164.35 kB 164.18 kB
oss-experimental/react-dom/cjs/react-dom-profiling.development.js = 966.42 kB 963.60 kB = 163.35 kB 163.18 kB
oss-experimental/react-reconciler/cjs/react-reconciler.development.js = 646.92 kB 645.01 kB = 103.84 kB 103.67 kB
oss-stable/react-reconciler/cjs/react-reconciler.development.js = 633.36 kB 631.48 kB = 101.98 kB 101.80 kB
oss-stable-rc/react-reconciler/cjs/react-reconciler.development.js = 633.34 kB 631.46 kB = 101.96 kB 101.78 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.development.js = 633.34 kB 631.46 kB = 101.96 kB 101.78 kB
facebook-www/ReactDOMTesting-prod.classic.js = 615.30 kB 613.47 kB = 109.92 kB 109.81 kB
facebook-www/ReactReconciler-dev.classic.js = 739.04 kB 736.85 kB = 118.07 kB 117.85 kB
oss-experimental/react-dom/cjs/react-dom-client.development.js = 949.98 kB 947.15 kB = 160.52 kB 160.36 kB
facebook-www/ReactDOMTesting-dev.classic.js = 1,101.40 kB 1,098.06 kB = 185.93 kB 185.57 kB
facebook-www/ReactDOM-prod.classic.js = 600.56 kB 598.74 kB = 106.23 kB 106.09 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.production.js = 526.96 kB 525.35 kB = 95.15 kB 95.13 kB
facebook-www/ReactDOM-dev.classic.js = 1,084.49 kB 1,081.15 kB = 181.96 kB 181.62 kB
facebook-www/ReactDOMTesting-prod.modern.js = 591.58 kB 589.76 kB = 106.08 kB 105.99 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js = 512.23 kB 510.62 kB = 91.47 kB 91.45 kB
facebook-www/ReactDOM-prod.modern.js = 576.85 kB 575.03 kB = 102.37 kB 102.27 kB
oss-stable/react-dom/cjs/react-dom-client.production.js = 505.04 kB 503.41 kB = 90.26 kB 90.27 kB
oss-stable-rc/react-dom/cjs/react-dom-client.production.js = 504.93 kB 503.30 kB = 90.24 kB 90.24 kB
oss-stable-semver/react-dom/cjs/react-dom-client.production.js = 504.93 kB 503.30 kB = 90.24 kB 90.24 kB
facebook-react-native/react-test-renderer/cjs/ReactTestRenderer-profiling.js = 345.77 kB 344.55 kB = 60.27 kB 60.13 kB
react-native/implementations/ReactNativeRenderer-prod.js = 359.20 kB 357.84 kB = 62.90 kB 62.78 kB
facebook-www/ReactDOMTesting-dev.modern.js = 1,065.55 kB 1,061.24 kB = 179.91 kB 179.48 kB
facebook-www/ReactDOM-dev.modern.js = 1,048.64 kB 1,044.33 kB = 176.04 kB 175.60 kB
facebook-react-native/react-test-renderer/cjs/ReactTestRenderer-dev.js = 579.38 kB 577.00 kB = 94.62 kB 94.23 kB
react-native/implementations/ReactNativeRenderer-prod.fb.js = 383.02 kB 381.37 kB = 67.04 kB 66.87 kB
facebook-www/ReactReconciler-dev.modern.js = 715.19 kB 712.09 kB = 114.03 kB 113.72 kB
facebook-www/ReactART-prod.classic.js = 367.66 kB 365.98 kB = 62.19 kB 62.11 kB
oss-experimental/react-test-renderer/cjs/react-test-renderer.development.js = 548.67 kB 546.15 kB = 89.90 kB 89.44 kB
oss-stable/react-test-renderer/cjs/react-test-renderer.development.js = 546.29 kB 543.78 kB = 89.49 kB 89.06 kB
oss-stable-rc/react-test-renderer/cjs/react-test-renderer.development.js = 546.23 kB 543.71 kB = 89.47 kB 89.03 kB
oss-stable-semver/react-test-renderer/cjs/react-test-renderer.development.js = 546.23 kB 543.71 kB = 89.47 kB 89.03 kB
oss-experimental/react-art/cjs/react-art.production.js = 302.20 kB 300.78 kB = 51.97 kB 51.83 kB
facebook-www/ReactART-prod.modern.js = 350.65 kB 348.97 kB = 59.44 kB 59.35 kB
facebook-react-native/react-test-renderer/cjs/ReactTestRenderer-prod.js = 322.40 kB 320.65 kB = 56.80 kB 56.66 kB
oss-experimental/react-test-renderer/cjs/react-test-renderer.production.js = 307.17 kB 305.42 kB = 54.39 kB 54.21 kB
oss-stable/react-test-renderer/cjs/react-test-renderer.production.js = 304.97 kB 303.22 kB = 53.95 kB 53.77 kB
oss-stable-rc/react-test-renderer/cjs/react-test-renderer.production.js = 304.91 kB 303.16 kB = 53.92 kB 53.75 kB
oss-stable-semver/react-test-renderer/cjs/react-test-renderer.production.js = 304.91 kB 303.16 kB = 53.92 kB 53.75 kB
oss-stable/react-art/cjs/react-art.production.js = 295.74 kB 294.04 kB = 50.80 kB 50.62 kB
oss-stable-rc/react-art/cjs/react-art.production.js = 295.68 kB 293.98 kB = 50.78 kB 50.60 kB
oss-stable-semver/react-art/cjs/react-art.production.js = 295.68 kB 293.98 kB = 50.78 kB 50.60 kB
facebook-www/ReactTestRenderer-dev.classic.js = 573.40 kB 569.90 kB = 93.95 kB 93.46 kB
facebook-www/ReactTestRenderer-dev.modern.js = 573.39 kB 569.90 kB = 93.95 kB 93.46 kB
facebook-www/ReactART-dev.classic.js = 652.62 kB 648.58 kB = 104.84 kB 104.27 kB
oss-experimental/react-art/cjs/react-art.development.js = 565.04 kB 560.85 kB = 91.23 kB 90.73 kB
oss-stable/react-art/cjs/react-art.development.js = 551.02 kB 546.90 kB = 89.39 kB 88.92 kB
oss-stable-rc/react-art/cjs/react-art.development.js = 550.95 kB 546.84 kB = 89.37 kB 88.90 kB
oss-stable-semver/react-art/cjs/react-art.development.js = 550.95 kB 546.84 kB = 89.37 kB 88.90 kB
facebook-www/ReactART-dev.modern.js = 630.18 kB 625.25 kB = 101.16 kB 100.53 kB

Generated by 🚫 dangerJS against 03000dd

josephsavona added a commit that referenced this pull request Sep 5, 2024
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: b3e3b82
Pull Request resolved: #30889
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-poisoned]
josephsavona added a commit that referenced this pull request Sep 5, 2024
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: a71a783
Pull Request resolved: #30889
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-poisoned]
josephsavona added a commit that referenced this pull request Sep 5, 2024
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: 62875e6
Pull Request resolved: #30889
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-poisoned]
josephsavona added a commit that referenced this pull request Sep 5, 2024
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: 8bab4b4
Pull Request resolved: #30889
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-poisoned]
josephsavona added a commit that referenced this pull request Sep 5, 2024
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: 4c6350a
Pull Request resolved: #30889
Copy link
Member

@kassens kassens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense

…r on "Fix useMemoCache with setState in render"

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-poisoned]
josephsavona added a commit that referenced this pull request Sep 5, 2024
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: 4d25c92
Pull Request resolved: #30889
Comment on lines 638 to 642
// Because we clone/reset the memo cache after every aborted attempt, we
// must process the first chunk again.
//
// That's three total times we've processed the first chunk, compared to
// just once when enableNoCloningMemoCache is on.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like this reset was just an artifact of the renderWithHooksAgain() reset. so the feature flag helps, but a bit less than we expected (we process the chunk once instead of twice)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm nope, more complicated than that. Tests seem to be failing on persistent mode with this change, still debugging.

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-poisoned]
josephsavona added a commit that referenced this pull request Sep 6, 2024
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: d0508ab
Pull Request resolved: #30889
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-poisoned]
josephsavona added a commit that referenced this pull request Sep 6, 2024
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: 57608c8
Pull Request resolved: #30889
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-poisoned]
josephsavona added a commit that referenced this pull request Sep 6, 2024
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: ab48eac
Pull Request resolved: #30889
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-poisoned]
josephsavona added a commit that referenced this pull request Sep 6, 2024
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: 50bf0ce
Pull Request resolved: #30889
…tate in render"

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-poisoned]
josephsavona added a commit that referenced this pull request Sep 6, 2024
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: fc0947c
Pull Request resolved: #30889
Comment on lines +2523 to +2531
}
const lastEffect = componentUpdateQueue.lastEffect;
if (lastEffect === null) {
componentUpdateQueue.lastEffect = effect.next = effect;
} else {
const lastEffect = componentUpdateQueue.lastEffect;
if (lastEffect === null) {
componentUpdateQueue.lastEffect = effect.next = effect;
} else {
const firstEffect = lastEffect.next;
lastEffect.next = effect;
effect.next = firstEffect;
componentUpdateQueue.lastEffect = effect;
}
const firstEffect = lastEffect.next;
lastEffect.next = effect;
effect.next = firstEffect;
componentUpdateQueue.lastEffect = effect;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drive by cleanup since i was here

@josephsavona josephsavona merged commit 03000dd into gh/josephsavona/56/base Sep 6, 2024
184 checks passed
josephsavona added a commit that referenced this pull request Sep 6, 2024
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: fc0947c
Pull Request resolved: #30889
@josephsavona josephsavona deleted the gh/josephsavona/56/head branch September 6, 2024 21:32
github-actions bot pushed a commit that referenced this pull request Sep 6, 2024
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: fc0947c
Pull Request resolved: #30889

DiffTrain build for commit 727b361.
github-actions bot pushed a commit that referenced this pull request Sep 6, 2024
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: fc0947c
Pull Request resolved: #30889

DiffTrain build for [727b361](727b361)
gnoff pushed a commit to vercel/next.js that referenced this pull request Sep 12, 2024
**breaking change for canary users: Bumps peer dependency of React from
`19.0.0-rc-7771d3a7-20240827` to `19.0.0-rc-94e652d5-20240912`**

[diff
facebook/react@7771d3a7...94e652d5](facebook/react@7771d3a...94e652d)

<details>
<summary>React upstream changes</summary>

- facebook/react#30952
- facebook/react#30950
- facebook/react#30946
- facebook/react#30934
- facebook/react#30947
- facebook/react#30945
- facebook/react#30938
- facebook/react#30936
- facebook/react#30879
- facebook/react#30888
- facebook/react#30931
- facebook/react#30930
- facebook/react#30832
- facebook/react#30929
- facebook/react#30926
- facebook/react#30925
- facebook/react#30905
- facebook/react#30900
- facebook/react#30910
- facebook/react#30906
- facebook/react#30899
- facebook/react#30919
- facebook/react#30708
- facebook/react#30907
- facebook/react#30897
- facebook/react#30896
- facebook/react#30895
- facebook/react#30887
- facebook/react#30889
- facebook/react#30893
- facebook/react#30892
- facebook/react#30891
- facebook/react#30882
- facebook/react#30881
- facebook/react#30870
- facebook/react#30849
- facebook/react#30878
- facebook/react#30865
- facebook/react#30869
- facebook/react#30875
- facebook/react#30800
- facebook/react#30762
- facebook/react#30831
- facebook/react#30866
- facebook/react#30853
- facebook/react#30850
- facebook/react#30847
- facebook/react#30842
- facebook/react#30837
- facebook/react#30848
- facebook/react#30844
- facebook/react#30839
- facebook/react#30802
- facebook/react#30841
- facebook/react#30827
- facebook/react#30826
- facebook/react#30825
- facebook/react#30824
- facebook/react#30840
- facebook/react#30838
- facebook/react#30836
- facebook/react#30819
- facebook/react#30816
- facebook/react#30814
- facebook/react#30813
- facebook/react#30812
- facebook/react#30811

</details>

---------

Co-authored-by: vercel-release-bot <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed React Core Team Opened by a member of the React Core Team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants