1- import { PureComponent , Component } from "react"
1+ import { PureComponent , Component , createRef } from "react"
22import {
33 createAtom ,
44 _allowStateChanges ,
@@ -10,6 +10,11 @@ import {
1010import { isUsingStaticRendering } from "mobx-react-lite"
1111
1212import { newSymbol , shallowEqual , setHiddenProp , patch } from "./utils/utils"
13+ import {
14+ addReactionToTrack ,
15+ reactionToTrackSymbol ,
16+ recordReactionAsCommitted
17+ } from "mobx-react-lite"
1318
1419const mobxAdminProperty = $mobx || "$mobx" // BC
1520const mobxObserverProperty = newSymbol ( "isMobXReactObserver" )
@@ -66,14 +71,40 @@ export function makeClassComponentObserver(
6671 )
6772 }
6873 target . render = function ( ) {
74+ if ( ! this [ reactionToTrackSymbol ] ) {
75+ this [ reactionToTrackSymbol ] = createRef ( )
76+ }
6977 this . render = isUsingStaticRendering ( )
7078 ? originalRender
7179 : createReactiveRender . call ( this , originalRender )
7280 return this . render ( )
7381 }
7482 patch ( target , "componentDidMount" , function ( ) {
7583 this [ mobxIsUnmounted ] = false
76- if ( ! this . render [ mobxAdminProperty ] ) {
84+ recordReactionAsCommitted ( this [ reactionToTrackSymbol ] )
85+ let hasUpdated = false
86+ if ( this [ reactionToTrackSymbol ] . current ) {
87+ this [ reactionToTrackSymbol ] . current . mounted = true
88+ if ( this [ reactionToTrackSymbol ] . current . changedBeforeMount ) {
89+ this [ reactionToTrackSymbol ] . current . changedBeforeMount = false
90+ hasUpdated = true
91+ Component . prototype . forceUpdate . call ( this )
92+ }
93+ ! this . render [ mobxAdminProperty ]
94+ } else {
95+ const initialName = getDisplayName ( this )
96+ this [ reactionToTrackSymbol ] . current = {
97+ reaction : new Reaction ( `${ initialName } .render()` , ( ) => {
98+ Component . prototype . forceUpdate . call ( this )
99+ } ) ,
100+ mounted : true ,
101+ changedBeforeMount : false ,
102+ cleanAt : Infinity
103+ }
104+ hasUpdated = true
105+ Component . prototype . forceUpdate . call ( this )
106+ }
107+ if ( ! this . render [ mobxAdminProperty ] && ! hasUpdated ) {
77108 // Reaction is re-created automatically during render, but a component can re-mount and skip render #3395.
78109 // To re-create the reaction and re-subscribe to relevant observables we have to force an update.
79110 Component . prototype . forceUpdate . call ( this )
@@ -84,6 +115,8 @@ export function makeClassComponentObserver(
84115 return
85116 }
86117
118+ this [ reactionToTrackSymbol ] . current = null
119+
87120 const reaction = this . render [ mobxAdminProperty ]
88121 if ( reaction ) {
89122 reaction . dispose ( )
@@ -143,13 +176,18 @@ function createReactiveRender(originalRender: any) {
143176 try {
144177 setHiddenProp ( this , isForcingUpdateKey , true )
145178 if ( ! this [ skipRenderKey ] ) {
146- Component . prototype . forceUpdate . call ( this )
179+ if ( this [ reactionToTrackSymbol ] . current . mounted ) {
180+ Component . prototype . forceUpdate . call ( this )
181+ } else {
182+ this [ reactionToTrackSymbol ] . current . changedBeforeMount = true
183+ }
147184 }
148185 hasError = false
149186 } finally {
150187 setHiddenProp ( this , isForcingUpdateKey , false )
151188 if ( hasError ) {
152189 reaction . dispose ( )
190+ this [ reactionToTrackSymbol ] . current = null
153191 // Forces reaction to be re-created on next render
154192 this . render [ mobxAdminProperty ] = null
155193 }
@@ -165,6 +203,11 @@ function createReactiveRender(originalRender: any) {
165203 isRenderingPending = false
166204 // Create reaction lazily to support re-mounting #3395
167205 const reaction = ( reactiveRender [ mobxAdminProperty ] ??= createReaction ( ) )
206+
207+ if ( ! this [ reactionToTrackSymbol ] . current ) {
208+ addReactionToTrack ( this [ reactionToTrackSymbol ] , reaction , { } )
209+ }
210+
168211 let exception : unknown = undefined
169212 let rendering = undefined
170213 reaction . track ( ( ) => {
0 commit comments