@@ -17,8 +17,8 @@ cfg_if! {
1717
1818/// Updates for a `Component` instance. Used by scope sender.
1919pub ( crate ) enum ComponentUpdate < COMP : Component > {
20- /// Force update
21- Force ,
20+ /// First update
21+ First ,
2222 /// Wraps messages for a component.
2323 Message ( COMP :: Message ) ,
2424 /// Wraps batch of messages for a component.
@@ -159,7 +159,10 @@ impl<COMP: Component> Scope<COMP> {
159159 node_ref : NodeRef ,
160160 props : COMP :: Properties ,
161161 ) -> Scope < COMP > {
162- scheduler ( ) . push_comp (
162+ let scheduler = scheduler ( ) ;
163+ // Hold scheduler lock so that `create` doesn't run until `update` is scheduled
164+ let lock = scheduler. lock ( ) ;
165+ scheduler. push_comp (
163166 ComponentRunnableType :: Create ,
164167 Box :: new ( CreateComponent {
165168 state : self . state . clone ( ) ,
@@ -171,28 +174,19 @@ impl<COMP: Component> Scope<COMP> {
171174 props,
172175 } ) ,
173176 ) ;
174- self . update ( ComponentUpdate :: Force , true ) ;
177+ self . update ( ComponentUpdate :: First ) ;
178+ drop ( lock) ;
179+ scheduler. start ( ) ;
175180 self
176181 }
177182
178183 /// Schedules a task to send an update to a component
179- pub ( crate ) fn update ( & self , update : ComponentUpdate < COMP > , first_update : bool ) {
184+ pub ( crate ) fn update ( & self , update : ComponentUpdate < COMP > ) {
180185 let update = UpdateComponent {
181186 state : self . state . clone ( ) ,
182187 update,
183188 } ;
184189 scheduler ( ) . push_comp ( ComponentRunnableType :: Update , Box :: new ( update) ) ;
185- self . render ( first_update) ;
186- }
187-
188- /// Schedules a task to render the component and call its rendered method
189- pub ( crate ) fn render ( & self , first_render : bool ) {
190- let state = self . state . clone ( ) ;
191- let rendered = RenderComponent {
192- state,
193- first_render,
194- } ;
195- scheduler ( ) . push_comp ( ComponentRunnableType :: Render , Box :: new ( rendered) ) ;
196190 }
197191
198192 /// Send a message to the component.
@@ -203,7 +197,7 @@ impl<COMP: Component> Scope<COMP> {
203197 where
204198 T : Into < COMP :: Message > ,
205199 {
206- self . update ( ComponentUpdate :: Message ( msg. into ( ) ) , false ) ;
200+ self . update ( ComponentUpdate :: Message ( msg. into ( ) ) ) ;
207201 }
208202
209203 /// Send a batch of messages to the component.
@@ -215,7 +209,7 @@ impl<COMP: Component> Scope<COMP> {
215209 /// Please be aware that currently this method synchronously
216210 /// schedules calls to the [Component](Component) interface.
217211 pub fn send_message_batch ( & self , messages : Vec < COMP :: Message > ) {
218- self . update ( ComponentUpdate :: MessageBatch ( messages) , false ) ;
212+ self . update ( ComponentUpdate :: MessageBatch ( messages) ) ;
219213 }
220214
221215 /// Creates a `Callback` which will send a message to the linked
@@ -285,6 +279,7 @@ struct ComponentState<COMP: Component> {
285279 last_root : Option < VNode > ,
286280 new_root : Option < VNode > ,
287281 has_rendered : bool ,
282+ pending_updates : Vec < Box < UpdateComponent < COMP > > > ,
288283}
289284
290285impl < COMP : Component > ComponentState < COMP > {
@@ -309,6 +304,7 @@ impl<COMP: Component> ComponentState<COMP> {
309304 last_root : None ,
310305 new_root : None ,
311306 has_rendered : false ,
307+ pending_updates : Vec :: new ( ) ,
312308 }
313309 }
314310}
@@ -362,9 +358,20 @@ where
362358 COMP : Component ,
363359{
364360 fn run ( self : Box < Self > ) {
365- if let Some ( mut state) = self . state . borrow_mut ( ) . as_mut ( ) {
361+ let state_clone = self . state . clone ( ) ;
362+ if let Some ( mut state) = state_clone. borrow_mut ( ) . as_mut ( ) {
363+ if state. new_root . is_some ( ) {
364+ state. pending_updates . push ( self ) ;
365+ return ;
366+ }
367+
368+ let first_update = match self . update {
369+ ComponentUpdate :: First => true ,
370+ _ => false ,
371+ } ;
372+
366373 let should_update = match self . update {
367- ComponentUpdate :: Force => true ,
374+ ComponentUpdate :: First => true ,
368375 ComponentUpdate :: Message ( message) => state. component . update ( message) ,
369376 ComponentUpdate :: MessageBatch ( messages) => messages
370377 . into_iter ( )
@@ -378,8 +385,15 @@ where
378385
379386 if should_update {
380387 state. new_root = Some ( state. component . render ( ) ) ;
388+ scheduler ( ) . push_comp (
389+ ComponentRunnableType :: Render ,
390+ Box :: new ( RenderComponent {
391+ state : self . state ,
392+ first_render : first_update,
393+ } ) ,
394+ ) ;
381395 } ;
382- }
396+ } ;
383397 }
384398}
385399
@@ -445,6 +459,9 @@ where
445459
446460 state. has_rendered = true ;
447461 state. component . rendered ( self . first_render ) ;
462+ for update in state. pending_updates . drain ( ..) {
463+ scheduler ( ) . push_comp ( ComponentRunnableType :: Update , update) ;
464+ }
448465 }
449466 }
450467}
@@ -523,6 +540,7 @@ mod tests {
523540 struct Props {
524541 lifecycle : Rc < RefCell < Vec < String > > > ,
525542 create_message : Option < bool > ,
543+ update_message : RefCell < Option < bool > > ,
526544 view_message : RefCell < Option < bool > > ,
527545 rendered_message : RefCell < Option < bool > > ,
528546 }
@@ -555,6 +573,9 @@ mod tests {
555573 }
556574
557575 fn update ( & mut self , msg : Self :: Message ) -> ShouldRender {
576+ if let Some ( msg) = self . props . update_message . borrow_mut ( ) . take ( ) {
577+ self . link . send_message ( msg) ;
578+ }
558579 self . props
559580 . lifecycle
560581 . borrow_mut ( )
@@ -619,10 +640,10 @@ mod tests {
619640 } ,
620641 & vec ! [
621642 "create" . to_string( ) ,
622- "update(false)" . to_string( ) ,
623643 "view" . to_string( ) ,
624644 "child rendered" . to_string( ) ,
625645 "rendered(true)" . to_string( ) ,
646+ "update(false)" . to_string( ) ,
626647 ] ,
627648 ) ;
628649
@@ -635,10 +656,11 @@ mod tests {
635656 & vec ! [
636657 "create" . to_string( ) ,
637658 "view" . to_string( ) ,
638- "update(true)" . to_string( ) ,
639- "view" . to_string( ) ,
640659 "child rendered" . to_string( ) ,
641660 "rendered(true)" . to_string( ) ,
661+ "update(true)" . to_string( ) ,
662+ "view" . to_string( ) ,
663+ "rendered(false)" . to_string( ) ,
642664 ] ,
643665 ) ;
644666
@@ -651,9 +673,9 @@ mod tests {
651673 & vec ! [
652674 "create" . to_string( ) ,
653675 "view" . to_string( ) ,
654- "update(false)" . to_string( ) ,
655676 "child rendered" . to_string( ) ,
656677 "rendered(true)" . to_string( ) ,
678+ "update(false)" . to_string( ) ,
657679 ] ,
658680 ) ;
659681
@@ -688,5 +710,26 @@ mod tests {
688710 "rendered(false)" . to_string( ) ,
689711 ] ,
690712 ) ;
713+
714+ test_lifecycle (
715+ Props {
716+ lifecycle : lifecycle. clone ( ) ,
717+ create_message : Some ( true ) ,
718+ update_message : RefCell :: new ( Some ( true ) ) ,
719+ ..Props :: default ( )
720+ } ,
721+ & vec ! [
722+ "create" . to_string( ) ,
723+ "view" . to_string( ) ,
724+ "child rendered" . to_string( ) ,
725+ "rendered(true)" . to_string( ) ,
726+ "update(true)" . to_string( ) ,
727+ "view" . to_string( ) ,
728+ "rendered(false)" . to_string( ) ,
729+ "update(true)" . to_string( ) ,
730+ "view" . to_string( ) ,
731+ "rendered(false)" . to_string( ) ,
732+ ] ,
733+ ) ;
691734 }
692735}
0 commit comments