Bug: memory leak on props when parent doesn't change, but child using props changes (in the same jsx)

This issue has been created since 2022-11-10.

React version: 16.8 to 18.2.0

Steps To Reproduce

  1. pass a prop that has a big memory footprint to an element A
  2. A has a parent in the same jsx that doesn't change and doesn't use anything (e.g. a plain div)
  3. react renders A with the big prop BIG1
  4. change the bigprop and rerender
  5. react renders A with the big prop BIG2.
  6. A doesn't have a reference to BIG1 anymore. But the dom element of the parent of A that was rendered at step3 (which does have a reference to big1 through parentDomElement.reactPropsXXXXXX.children.A.props.big1) is reconciled (because the parent doesn't change) and reused as is, which prevents garbage collecting of big1. Nothing uses big1.

In my experience, this can happen in quite a lot of ways in practice. It does require one dom element (the parent) per leaked prop, but this is so pervasive that these elements may exist in a lot of places throughout the app, holding references to props at the instant of their render. The more instants at which different parts of the app are rendered, the more memory can be leaked. And if the app renders some kind of dynamic list that grows, then there is a practically unlimited supply of parent elements to hold old unused references.

It's also something that is very easy to introduce as a regression by simply starting to use a big variable in a closure (not even related to anything react, for example just mapping over an array), because it is then added to the context of all closures in this render function, some of which may be passed to react components as props.

Of course this happens all the time in a normal react app for all the props (increasing memory usage by (guessing) 10x or 20x), but this is not really a problem for most people where the whole app state described by all the props is probably less than 100kb (the app then uses megabytes of memory, which is fine by modern standards). Or for apps that naturally unmount the whole dom frequently, which does allow garbage collecting these old unused propos.

Link to code example:
this one is a "normal code" that has more chances of happening in practice (uses a closure that capture the big value as the prop leaking memory)
https://0xhtw5.csb.app/ (code: https://codesandbox.io/s/react-memory-leak-0xhtw5)

this one is a more artificial repro which is arguably more understandable:
https://1pw8bf.csb.app/ (code: https://codesandbox.io/s/react-memory-leak-plain-1pw8bf)

The current behavior

Any prop (and when passing closures as props, any variable of a render function used in at least one closure) may be retained by dom elements that are parents of elements that use these props in the same jsx, when the parent doesn't change at the same time as the child.

The expected behavior

Ideally, props of children should not be retained by dom elements of parents that don't even use them. If this is an inherent limitation of the react model, then maybe document it a lot with big warnings ? Add tools to detect it automatically ? Describe recommended code structure and pattern to avoid this problem ? Not sure..

Thanks in advance !

More Details About Repo
Owner Name facebook
Repo Name react
Full Name facebook/react
Language JavaScript
Created Date 2013-05-24
Updated Date 2022-12-01
Star Count 198482
Watcher Count 6646
Fork Count 41196
Issue Count 1106


Issue Title Created Date Comment Count Updated Date
Modify/amend generated configuration 2 2021-08-26 2022-11-30
Flash programming not working with the Colorlight i9 9 2022-04-23 2022-10-19
@JSONField(format="")设置无效 7 2022-05-30 2022-12-01
[FEAT] 콘텐츠 생성 flow 연결 0 2022-01-21 2022-10-10
Can't build for android 1 2021-10-12 2022-09-18
Controller Won't Show Up When Connected-Also Tested on gamepad tester 1 2021-06-03 2022-09-26
tableAttrs里添加elementui table的row-key属性不生效 0 2021-12-23 2022-11-06
Add randAddress function 0 2022-02-09 2022-11-20
Lexical analys and highlighting 1 2021-03-12 2022-10-01
Add TextBlock Widget 0 2020-07-28 2022-11-20
Cross account calls possible? 5 2021-01-26 2022-11-21
gcs_upload - when uploading dataframe directly includes row number 3 2021-02-10 2022-11-04
Language configuration fails for generated forms, e.g. subscription web form, for locale de-DE 2 2021-06-16 2022-07-07
How to block stackexchange but not stackoverflow? 1 2020-11-30 2022-11-20
Cactbot overlays randomly stop receiving data 5 2022-01-19 2022-10-17
WebPack / Require usage 16 2016-05-15 2022-10-22
Error loading libfluidsynth.dll 1 2022-11-02 2022-11-27
Restart on configmap or secret only 5 2020-08-25 2022-11-01
Multiplayer/Game Link Not working 5 2022-08-09 2022-10-27
setPadding function not working 3 2020-10-05 2022-11-28
overlay is closing when text is selected because mouseup is triggered when not hovered over overlay 3 2022-08-16 2022-10-02
NullReferenceException on Model.SubscriptionStatus for /landingpage 1 2021-03-11 2022-10-04
Question: For Media, is there buffering, and if so can we have a command to clear it? 3 2020-08-21 2022-10-03
Change `hhvm/hhvm:latest` to use main `distroname` repository, not `distroname-4.x` 1 2022-04-08 2022-10-05
Can select unnecessary objects in custom ERD creation window 0 2022-03-21 2022-10-10
Feature Request: Ability to rename terminals using shell commands 5 2022-03-03 2022-10-24
Memory leak issue potentially caused by rendering authenticity_token in meta tag 8 2020-12-11 2022-11-14
Enhancement: automatically generate (and activate) backup codes 3 2019-05-07 2022-11-09
TOTP: Verification Should Remove Spaces 3 2020-01-09 2022-11-30
Support configuring different OIDC IDPs in Supervisor that users can authenticate with to access same Kubernetes cluster 3 2022-01-20 2022-09-23
2.5.x - records is not published: Possible GEM error 1 2022-08-13 2022-08-28
Any output format other than table does not display `Time`, `Rows fetched` and `Hydrate calls` information 0 2022-11-08 2022-11-25
`compiler.watchMode` should be `true` when running `webpack-dev-server` 10 2022-05-31 2022-07-26
JIRA module: support querying for issues / tasks not assigned to me 2 2022-06-14 2022-10-19
Linker command failed with exit code 1 on latest packages 4 2022-03-03 2022-11-13
How do you read this data 2 2021-04-29 2022-11-12
github.com/go-sql-driver/mysql.(*mysqlConn).startWatcher.func1() /root/go/pkg/mod/github.com/go-sql-driver/[email protected]/connection.go:621 +0xaa created by github.com/go-sql-driver/mysql.(*mysqlConn).startWatcher /root/go/pkg/mod/github.com/go-sql-driver/[email protected]/connection.go:618 +0xfe goroutine 58728 [select, 612 minutes]: 3 2022-07-23 2022-11-23
A question about running train_transr_FB15K237.py 1 2022-05-08 2022-11-27
paddle中有没有,pytorch 中mask_fill对应的函数,paddle中mask_select是改变了shape 2 2020-10-25 2022-11-14
[BUG]新建分组(类型为:项目),设置分组权限(如:测试跟踪/接口测试),关联项目后,使用新增用户打开项目提示404错误(/case/node/publicCount/接口报错) 6 2022-06-06 2022-08-28
Fix code scanning alert - GHSA-8c26-wmh5-6g9v 1 2022-08-05 2022-09-24
Add support for PrivateLink parameters to NFS File Share Resource 3 2021-11-10 2022-11-16
Oracle DDL parser error 5 2022-02-26 2022-11-14
2.4R2 assembly manual page 40 text error 3 2022-07-05 2022-11-13
Manual Specifies wrong wire thickness. 2 2022-08-03 2022-11-13
Error exporting inference graph for spaghettinet 2 2021-12-01 2022-11-24
Changes to website do not require Netlify preview 9 2022-05-21 2022-11-20
[terra-application-navigation] UtilityMenu is not passing metaData to menuItems 0 2021-04-09 2022-11-20
Sentiment Tracking - 'View more details' link is misleading as it redirects to build analysis tab documentation 1 2022-04-25 2022-11-14
Inform developer when a character is used that has no glyph in the available fonts 6 2015-11-09 2022-10-04