@@ -36,24 +36,50 @@ type RootElem struct {
3636 Root * ComponentImpl
3737 RenderTs int64
3838 AppTitle string
39- CFuncs map [string ]any
39+ CFuncs map [string ]any // component name => render function
4040 CompMap map [string ]* ComponentImpl // component waveid -> component
4141 EffectWorkQueue []* EffectWorkElem
42- NeedsRenderMap map [string ]bool
43- Atoms map [string ]genAtom
42+ needsRenderMap map [string ]bool // key: waveid
43+ needsRenderLock sync.Mutex
44+ Atoms map [string ]genAtom // key: atomName
4445 atomLock sync.Mutex
4546 RefOperations []vdom.VDomRefOperation
4647 Client * ClientImpl
4748}
4849
49- func (r * RootElem ) AddRenderWork (id string ) {
50- if r .NeedsRenderMap == nil {
51- r .NeedsRenderMap = make (map [string ]bool )
50+ func (r * RootElem ) addRenderWork (id string ) {
51+ defer func () {
52+ if inContextType () == GlobalContextType_async {
53+ r .Client .notifyAsyncRenderWork ()
54+ }
55+ }()
56+
57+ r .needsRenderLock .Lock ()
58+ defer r .needsRenderLock .Unlock ()
59+
60+ if r .needsRenderMap == nil {
61+ r .needsRenderMap = make (map [string ]bool )
5262 }
53- r .NeedsRenderMap [id ] = true
63+ r .needsRenderMap [id ] = true
5464}
5565
56- func (r * RootElem ) AddEffectWork (id string , effectIndex int , compTag string ) {
66+ func (r * RootElem ) getAndClearRenderWork () []string {
67+ r .needsRenderLock .Lock ()
68+ defer r .needsRenderLock .Unlock ()
69+
70+ if len (r .needsRenderMap ) == 0 {
71+ return nil
72+ }
73+
74+ ids := make ([]string , 0 , len (r .needsRenderMap ))
75+ for id := range r .needsRenderMap {
76+ ids = append (ids , id )
77+ }
78+ r .needsRenderMap = nil
79+ return ids
80+ }
81+
82+ func (r * RootElem ) addEffectWork (id string , effectIndex int , compTag string ) {
5783 r .EffectWorkQueue = append (r .EffectWorkQueue , & EffectWorkElem {WaveId : id , EffectIndex : effectIndex , CompTag : compTag })
5884}
5985
@@ -135,8 +161,12 @@ func (r *RootElem) AtomAddRenderWork(atomName string) {
135161 if ! ok {
136162 return
137163 }
138- for _ , compId := range atom .GetUsedBy () {
139- r .AddRenderWork (compId )
164+ usedBy := atom .GetUsedBy ()
165+ if len (usedBy ) == 0 {
166+ return
167+ }
168+ for _ , compId := range usedBy {
169+ r .addRenderWork (compId )
140170 }
141171}
142172
@@ -356,8 +386,8 @@ func (r *RootElem) RunWork(opts *RenderOpts) {
356386 r .runEffect (work , hook )
357387 }
358388 // now check if we need a render
359- if len ( r . NeedsRenderMap ) > 0 {
360- r . NeedsRenderMap = nil
389+ renderIds := r . getAndClearRenderWork ()
390+ if len ( renderIds ) > 0 {
361391 r .render (r .Root .Elem , & r .Root , "root" , opts )
362392 }
363393}
@@ -392,7 +422,7 @@ func (r *RootElem) UpdateRef(updateRef rpctypes.VDomRefUpdate) {
392422 }
393423 ref .HasCurrent = updateRef .HasCurrent
394424 ref .Position = updateRef .Position
395- r .AddRenderWork (waveId )
425+ r .addRenderWork (waveId )
396426}
397427
398428func (r * RootElem ) QueueRefOp (op vdom.VDomRefOperation ) {
0 commit comments