Skip to content
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

Eager bailouts only for use state #18241

Closed

Conversation

Andarist
Copy link
Contributor

@Andarist Andarist commented Mar 6, 2020

Summary

fixes #15088 closes #15198

I've stumbled upon an edge case where bailed out actions were kept in the update queue and could be applied using the newly rendered reducer during future rerender. This can be observed here - https://codesandbox.io/s/silly-paper-22org . Just click the disable button, click the increment button multiple times and click the disable button once again. The counter will jump to the number of times you have clicked on the incrementing button while it really should still show 0.

@sebmarkbage has suggested ditching the eager bailout optimization for the useReducer case altogether here and @gaearon has recently encouraged me to just follow this suggestion.

@sebmarkbage has also suggested that "We should also forbid suspending in a setState reducer.", but I'm not sure what that means exactly and how it should be approached so any tips regarding that would be highly appreciated.

As to the implementation - I've managed to remove the need to store "lastRenderedReducer" at all and also I've decided to only append updates to the queue if the rerender is scheduled. In the current implementation on the master branch, the queue was slightly prone to a minor memory leak because theoretically, it was possible to append bailed out updates until the next rerender and that, theoretically, could never happen. This is not a real-life scenario, but it still seems better to avoid appending to the queue unnecessarily to avoid going through those updates during the next render.

Test Plan

I've run tests, lint & flow dom tasks before sending this as PR.

@@ -3173,6 +3123,59 @@ function loadModules({
expect(ReactNoop).toMatchRenderedOutput('5');
});

it('should not store dispatched items in the queue (TODO: better description)', () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure how to best describe this test as it sort of tests the mechanism that is no longer here (eager bailouts for use reducer).

@codesandbox-ci
Copy link

codesandbox-ci bot commented Mar 6, 2020

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 897945f:

Sandbox Source
sharp-night-0tygf Configuration
friendly-dubinsky-c6ut1 PR
sharp-poitras-1x07c Issue #15198

@sizebot
Copy link

sizebot commented Mar 6, 2020

Details of bundled changes.

Comparing: 4027f2a...897945f

react-dom

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
ReactDOM-profiling.js +0.2% +0.1% 412.95 KB 413.59 KB 75.11 KB 75.17 KB FB_WWW_PROFILING
react-dom-server.browser.development.js 0.0% 0.0% 135.28 KB 135.28 KB 34.78 KB 34.79 KB UMD_DEV
react-dom-unstable-fizz.node.production.min.js 0.0% 🔺+0.2% 1.15 KB 1.15 KB 654 B 655 B NODE_PROD
react-dom-server.browser.production.min.js 0.0% 0.0% 20.05 KB 20.05 KB 7.42 KB 7.42 KB UMD_PROD
react-dom-unstable-native-dependencies.development.js 0.0% 0.0% 55.86 KB 55.86 KB 14.46 KB 14.47 KB NODE_DEV
react-dom.development.js +0.1% -0.0% 885.67 KB 886.7 KB 195.23 KB 195.14 KB UMD_DEV
react-dom-unstable-native-dependencies.production.min.js 0.0% 🔺+0.1% 9.99 KB 9.99 KB 3.37 KB 3.37 KB NODE_PROD
react-dom.production.min.js 🔺+0.1% 0.0% 116.01 KB 116.18 KB 37.17 KB 37.17 KB UMD_PROD
react-dom.profiling.min.js +0.1% +0.1% 119.72 KB 119.89 KB 38.39 KB 38.42 KB UMD_PROFILING
react-dom.development.js +0.1% -0.0% 842.84 KB 843.82 KB 192.79 KB 192.73 KB NODE_DEV
react-dom.production.min.js 🔺+0.1% 🔺+0.1% 116.09 KB 116.26 KB 36.5 KB 36.53 KB NODE_PROD
react-dom-server.node.production.min.js 0.0% 0.0% 20.38 KB 20.38 KB 7.53 KB 7.53 KB NODE_PROD
react-dom.profiling.min.js +0.1% +0.1% 119.95 KB 120.12 KB 37.63 KB 37.65 KB NODE_PROFILING
ReactDOM-dev.js +0.1% -0.0% 950.85 KB 951.88 KB 212.11 KB 212.04 KB FB_WWW_DEV
ReactDOM-prod.js 🔺+0.2% 🔺+0.1% 401.18 KB 401.82 KB 72.85 KB 72.92 KB FB_WWW_PROD
react-dom-unstable-fizz.node.development.js 0.0% +0.1% 3.68 KB 3.68 KB 1.33 KB 1.33 KB NODE_DEV
ReactDOMTesting-dev.js +0.1% -0.0% 899.95 KB 900.99 KB 201.19 KB 201.13 KB FB_WWW_DEV
ReactDOMTesting-prod.js 🔺+0.2% 🔺+0.1% 382.29 KB 382.93 KB 69.64 KB 69.7 KB FB_WWW_PROD
react-dom-server.browser.development.js 0.0% 0.0% 128.35 KB 128.35 KB 34.36 KB 34.36 KB NODE_DEV
react-dom-test-utils.development.js 0.0% 0.0% 53.77 KB 53.77 KB 14 KB 14 KB UMD_DEV
ReactDOMTesting-profiling.js +0.2% +0.1% 382.29 KB 382.93 KB 69.64 KB 69.7 KB FB_WWW_PROFILING
react-dom-server.browser.production.min.js 0.0% 0.0% 19.97 KB 19.97 KB 7.38 KB 7.38 KB NODE_PROD
react-dom-test-utils.production.min.js 0.0% 0.0% 10.94 KB 10.94 KB 4.16 KB 4.16 KB UMD_PROD
react-dom-unstable-fizz.browser.production.min.js 0.0% 🔺+0.1% 1.17 KB 1.17 KB 691 B 692 B UMD_PROD
ReactDOMServer-prod.js 0.0% 0.0% 47.49 KB 47.49 KB 11.05 KB 11.05 KB FB_WWW_PROD
react-dom-test-utils.production.min.js 0.0% -0.0% 10.79 KB 10.79 KB 4.09 KB 4.09 KB NODE_PROD
react-dom-unstable-native-dependencies.development.js 0.0% 0.0% 58.9 KB 58.9 KB 14.7 KB 14.7 KB UMD_DEV
react-dom-unstable-native-dependencies.production.min.js 0.0% 0.0% 10.26 KB 10.26 KB 3.49 KB 3.49 KB UMD_PROD

react-native-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
ReactFabric-dev.js +0.1% -0.0% 615.89 KB 616.68 KB 133.23 KB 133.16 KB RN_OSS_DEV
ReactNativeRenderer-dev.js +0.2% -0.0% 633.94 KB 634.98 KB 137.56 KB 137.49 KB RN_OSS_DEV
ReactNativeRenderer-prod.js 🔺+0.2% 🔺+0.1% 259.8 KB 260.44 KB 45.2 KB 45.25 KB RN_OSS_PROD
ReactNativeRenderer-profiling.js +0.2% +0.1% 271.59 KB 272.23 KB 47.44 KB 47.5 KB RN_OSS_PROFILING
ReactFabric-prod.js 🔺+0.3% 🔺+0.1% 251.76 KB 252.4 KB 43.71 KB 43.77 KB RN_OSS_PROD
ReactFabric-profiling.js +0.2% +0.1% 263.56 KB 264.2 KB 45.98 KB 46.04 KB RN_OSS_PROFILING

react-art

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
ReactART-dev.js +0.1% -0.1% 569.13 KB 569.92 KB 119.38 KB 119.32 KB FB_WWW_DEV
ReactART-prod.js 🔺+0.3% 🔺+0.1% 233.84 KB 234.48 KB 39.73 KB 39.78 KB FB_WWW_PROD
react-art.development.js +0.1% -0.1% 616.35 KB 617.13 KB 130.17 KB 130.1 KB UMD_DEV
react-art.production.min.js 🔺+0.2% 0.0% 104.21 KB 104.38 KB 31.61 KB 31.61 KB UMD_PROD
react-art.development.js +0.1% -0.1% 521.24 KB 521.97 KB 112.53 KB 112.45 KB NODE_DEV
react-art.production.min.js 🔺+0.2% 🔺+0.2% 69.25 KB 69.41 KB 20.79 KB 20.83 KB NODE_PROD

react-test-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
ReactTestRenderer-dev.js +0.2% -0.1% 554.9 KB 555.93 KB 117.23 KB 117.16 KB FB_WWW_DEV
react-test-renderer-shallow.development.js 0.0% 0.0% 38.39 KB 38.39 KB 9.29 KB 9.29 KB UMD_DEV
react-test-renderer-shallow.production.min.js 0.0% 0.0% 12.91 KB 12.91 KB 3.93 KB 3.93 KB UMD_PROD
react-test-renderer.development.js +0.2% -0.1% 553.83 KB 554.86 KB 115.35 KB 115.27 KB UMD_DEV
react-test-renderer.production.min.js 🔺+0.2% 🔺+0.2% 71.22 KB 71.39 KB 21.66 KB 21.69 KB UMD_PROD
react-test-renderer.development.js +0.2% -0.1% 527.81 KB 528.78 KB 114.04 KB 113.98 KB NODE_DEV
react-test-renderer.production.min.js 🔺+0.2% 🔺+0.1% 71.04 KB 71.2 KB 21.34 KB 21.37 KB NODE_PROD

react-reconciler

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-reconciler.development.js +0.2% -0.1% 557.39 KB 558.37 KB 118 KB 117.94 KB NODE_DEV
react-reconciler-reflection.development.js 0.0% 0.0% 16.24 KB 16.24 KB 4.96 KB 4.96 KB NODE_DEV
react-reconciler.production.min.js 🔺+0.2% 🔺+0.1% 73.71 KB 73.87 KB 21.77 KB 21.79 KB NODE_PROD
react-reconciler-reflection.production.min.js 0.0% 🔺+0.1% 2.8 KB 2.8 KB 1.2 KB 1.2 KB NODE_PROD
react-reconciler-persistent.development.js +0.2% -0.1% 556.11 KB 557.08 KB 117.85 KB 117.79 KB NODE_DEV
react-reconciler-persistent.production.min.js 🔺+0.2% 🔺+0.1% 73.72 KB 73.88 KB 21.78 KB 21.8 KB NODE_PROD

ReactDOM: size: 0.0%, gzip: 0.0%

Size changes (stable)

Generated by 🚫 dangerJS against 897945f

@sizebot
Copy link

sizebot commented Mar 6, 2020

Details of bundled changes.

Comparing: 4027f2a...897945f

react-art

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-art.development.js +0.1% -0.1% 635.52 KB 636.3 KB 133.57 KB 133.5 KB UMD_DEV
react-art.production.min.js 🔺+0.2% 0.0% 106.64 KB 106.81 KB 32.25 KB 32.26 KB UMD_PROD
react-art.development.js +0.1% -0.1% 539.67 KB 540.4 KB 115.97 KB 115.89 KB NODE_DEV
react-art.production.min.js 🔺+0.2% 🔺+0.1% 71.62 KB 71.79 KB 21.44 KB 21.47 KB NODE_PROD
ReactART-dev.js +0.1% -0.1% 543.41 KB 544.2 KB 114.11 KB 114.04 KB FB_WWW_DEV
ReactART-prod.js 🔺+0.3% 🔺+0.1% 226.66 KB 227.3 KB 38.52 KB 38.58 KB FB_WWW_PROD

react-native-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
ReactNativeRenderer-prod.js 🔺+0.2% 🔺+0.1% 259.81 KB 260.45 KB 45.21 KB 45.26 KB RN_OSS_PROD
ReactNativeRenderer-profiling.js +0.2% +0.1% 271.61 KB 272.25 KB 47.45 KB 47.51 KB RN_OSS_PROFILING
ReactFabric-prod.js 🔺+0.3% 🔺+0.1% 251.77 KB 252.41 KB 43.72 KB 43.78 KB RN_OSS_PROD
ReactFabric-profiling.js +0.2% +0.1% 263.57 KB 264.21 KB 45.99 KB 46.04 KB RN_OSS_PROFILING
ReactFabric-dev.js +0.1% -0.0% 618.62 KB 619.41 KB 133.57 KB 133.5 KB RN_FB_DEV
ReactFabric-prod.js 🔺+0.3% 🔺+0.1% 251.93 KB 252.57 KB 43.75 KB 43.81 KB RN_FB_PROD
ReactNativeRenderer-dev.js +0.2% -0.0% 633.96 KB 634.99 KB 137.57 KB 137.5 KB RN_OSS_DEV
ReactFabric-profiling.js +0.2% +0.1% 263.72 KB 264.36 KB 46.02 KB 46.08 KB RN_FB_PROFILING
ReactNativeRenderer-dev.js +0.2% -0.0% 636.67 KB 637.7 KB 137.91 KB 137.85 KB RN_FB_DEV
ReactNativeRenderer-prod.js 🔺+0.2% 🔺+0.1% 259.96 KB 260.59 KB 45.23 KB 45.29 KB RN_FB_PROD
ReactNativeRenderer-profiling.js +0.2% +0.1% 271.75 KB 272.39 KB 47.48 KB 47.54 KB RN_FB_PROFILING
ReactFabric-dev.js +0.1% -0.0% 615.91 KB 616.7 KB 133.23 KB 133.17 KB RN_OSS_DEV

react-dom

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-dom.profiling.min.js +0.1% +0.1% 124.01 KB 124.18 KB 38.69 KB 38.73 KB NODE_PROFILING
react-dom-unstable-native-dependencies.development.js 0.0% 0.0% 58.91 KB 58.91 KB 14.71 KB 14.71 KB UMD_DEV
ReactDOM-dev.js +0.1% -0.0% 907.29 KB 908.32 KB 202.52 KB 202.45 KB FB_WWW_DEV
react-dom-unstable-native-dependencies.production.min.js 0.0% 0.0% 10.27 KB 10.27 KB 3.5 KB 3.5 KB UMD_PROD
ReactDOMServer-dev.js 0.0% 0.0% 137.4 KB 137.4 KB 35.11 KB 35.11 KB FB_WWW_DEV
react-dom-test-utils.development.js 0.0% 0.0% 53.78 KB 53.78 KB 14.01 KB 14.01 KB UMD_DEV
react-dom-test-utils.production.min.js 0.0% 0.0% 10.96 KB 10.96 KB 4.17 KB 4.17 KB UMD_PROD
ReactDOMTesting-dev.js +0.1% -0.0% 873.31 KB 874.35 KB 195.61 KB 195.55 KB FB_WWW_DEV
ReactDOMTesting-prod.js 🔺+0.2% 🔺+0.1% 368.74 KB 369.38 KB 67.46 KB 67.51 KB FB_WWW_PROD
ReactDOMTesting-profiling.js +0.2% +0.1% 368.74 KB 369.38 KB 67.46 KB 67.51 KB FB_WWW_PROFILING
react-dom-server.node.development.js 0.0% 0.0% 131.08 KB 131.08 KB 34.83 KB 34.84 KB NODE_DEV
react-dom-test-utils.production.min.js 0.0% -0.0% 10.81 KB 10.81 KB 4.1 KB 4.1 KB NODE_PROD
react-dom-server.node.production.min.js 0.0% 0.0% 20.83 KB 20.83 KB 7.61 KB 7.61 KB NODE_PROD
react-dom.development.js +0.1% -0.0% 914.35 KB 915.39 KB 200.16 KB 200.08 KB UMD_DEV
react-dom-server.browser.development.js 0.0% 0.0% 136.87 KB 136.87 KB 34.99 KB 34.99 KB UMD_DEV
react-dom.production.min.js 🔺+0.1% 0.0% 119.89 KB 120.05 KB 38.28 KB 38.3 KB UMD_PROD
react-dom-server.browser.production.min.js 0.0% 0.0% 20.51 KB 20.51 KB 7.51 KB 7.51 KB UMD_PROD
react-dom.profiling.min.js +0.1% -0.0% 123.71 KB 123.88 KB 39.53 KB 39.53 KB UMD_PROFILING
react-dom.development.js +0.1% -0.0% 870.34 KB 871.32 KB 197.7 KB 197.63 KB NODE_DEV
react-dom-server.browser.development.js 0.0% 0.0% 129.87 KB 129.87 KB 34.58 KB 34.58 KB NODE_DEV
react-dom.production.min.js 🔺+0.1% 0.0% 120.04 KB 120.21 KB 37.53 KB 37.54 KB NODE_PROD
react-dom-server.browser.production.min.js 0.0% 0.0% 20.43 KB 20.43 KB 7.46 KB 7.46 KB NODE_PROD
ReactDOM-prod.js 🔺+0.2% 🔺+0.1% 376.26 KB 376.9 KB 68.37 KB 68.42 KB FB_WWW_PROD
ReactDOMServer-prod.js 0.0% 0.0% 46.78 KB 46.78 KB 10.87 KB 10.87 KB FB_WWW_PROD
ReactDOM-profiling.js +0.2% +0.1% 387.95 KB 388.59 KB 70.54 KB 70.6 KB FB_WWW_PROFILING
react-dom-unstable-native-dependencies.development.js 0.0% 0.0% 55.87 KB 55.87 KB 14.47 KB 14.47 KB NODE_DEV
react-dom-unstable-fizz.node.development.js 0.0% +0.1% 3.69 KB 3.69 KB 1.34 KB 1.34 KB NODE_DEV
react-dom-unstable-native-dependencies.production.min.js 0.0% 🔺+0.1% 10 KB 10 KB 3.37 KB 3.38 KB NODE_PROD
react-dom-unstable-fizz.node.production.min.js 0.0% 🔺+0.2% 1.16 KB 1.16 KB 663 B 664 B NODE_PROD
react-dom-unstable-fizz.browser.development.js 0.0% +0.1% 3.35 KB 3.35 KB 1.27 KB 1.27 KB UMD_DEV
react-dom-unstable-fizz.browser.production.min.js 0.0% 🔺+0.1% 1.19 KB 1.19 KB 699 B 700 B UMD_PROD

react-test-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
ReactTestRenderer-dev.js +0.2% -0.1% 554.91 KB 555.95 KB 117.23 KB 117.16 KB FB_WWW_DEV
react-test-renderer-shallow.development.js 0.0% 0.0% 38.4 KB 38.4 KB 9.3 KB 9.3 KB UMD_DEV
react-test-renderer-shallow.production.min.js 0.0% 0.0% 12.92 KB 12.92 KB 3.94 KB 3.94 KB UMD_PROD
react-test-renderer.development.js +0.2% -0.1% 553.85 KB 554.89 KB 115.37 KB 115.29 KB UMD_DEV
react-test-renderer.production.min.js 🔺+0.2% 🔺+0.2% 71.25 KB 71.41 KB 21.67 KB 21.7 KB UMD_PROD
react-test-renderer.development.js +0.2% -0.1% 527.83 KB 528.81 KB 114.05 KB 114 KB NODE_DEV
react-test-renderer.production.min.js 🔺+0.2% 🔺+0.1% 71.06 KB 71.23 KB 21.36 KB 21.38 KB NODE_PROD

react-reconciler

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-reconciler-persistent.development.js +0.2% -0.1% 556.12 KB 557.1 KB 117.86 KB 117.79 KB NODE_DEV
react-reconciler-reflection.development.js 0.0% 0.0% 16.25 KB 16.25 KB 4.97 KB 4.97 KB NODE_DEV
react-reconciler-persistent.production.min.js 🔺+0.2% 🔺+0.1% 73.73 KB 73.9 KB 21.78 KB 21.81 KB NODE_PROD
react-reconciler.development.js +0.2% -0.1% 578.15 KB 579.12 KB 121.89 KB 121.81 KB NODE_DEV
react-reconciler.production.min.js 🔺+0.2% 🔺+0.1% 76.48 KB 76.65 KB 22.44 KB 22.46 KB NODE_PROD

ReactDOM: size: 0.0%, gzip: 0.0%

Size changes (experimental)

Generated by 🚫 dangerJS against 897945f

}
}

function setState<S>(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

For now this is being split from the dispatchAction but they both share pretty much the same implementation - besides the fact that dispatchAction has no eager bailout implemented.

Both could be collapsed into a single function and the eager bailout could only be attempted for reducer === basicStateReducer but to do that I would have to bring back keeping track of lastRenderedReducer.

Let me know which approach do you prefer.

@gaearon
Copy link
Collaborator

gaearon commented Apr 1, 2020

So we've been looking at this. It's probably the right thing to do. But it's a scary change. So we'd want it behind a flag. The current implementation in this PR would be hard to put behind a flag. It would also be hard to maintain two versions in one place.

We plan to fork the reconciler with a few other breaking and more ambitious changes. So we'll probably fix this as a part of that refactor. Thank you for starting this work though (and for flagging the issue in the first place). It's been really helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

useReducer - eagerReducer optimization discussion/questions
5 participants