Skip to content

Commit 146d46f

Browse files
ISSUE-139957: fixing infinite loop caused by initing component to early
1 parent 6a1c312 commit 146d46f

12 files changed

+37
-16
lines changed

scripts/dxcomponents/components-manager.js

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,23 @@ export class ComponentsManager {
3030

3131
/**
3232
* Creates a component.
33+
*
34+
* Warning: We cannot init() component here because it may cause infinite loop.
35+
* If we init() child before adding it to parent the following flow may occur:
36+
* 1. Parent creates child (but does not add it to its children list yet)
37+
* 2. Child init() is called
38+
* 3. Parent is updated (because of redux store update)
39+
* 4. Parent creates child again because its children list is empty.
40+
* 5. Child init() is called again - and loops occurs.
41+
*
3342
* @param type - type of component to create
3443
* @param args - arguments to pass to the component's constructor
3544
* @param init - if true, calls the component's init() method after creation
3645
* @returns the created component
3746
*/
38-
create(type, args = [], init = true) {
47+
create(type, args = []) {
3948
const ComponentClass = getComponentFromMap(type);
40-
const component = new ComponentClass(this, ...args);
41-
if (init) {
42-
component.init();
43-
}
44-
return component;
49+
return new ComponentClass(this, ...args);
4550
}
4651

4752
/**
@@ -52,12 +57,12 @@ export class ComponentsManager {
5257
* @param init - if true, calls the component's init() method after creation
5358
* @returns created or updated component
5459
*/
55-
upsert(component, type, args = [], init = true) {
60+
upsert(component, type, args = []) {
5661
if (component) {
5762
component.update(...args);
5863
return component;
5964
} else {
60-
return this.create(type, args, init);
65+
return this.create(type, args);
6166
}
6267
}
6368
}

scripts/dxcomponents/components/containers/assignment-card.component.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export class AssignmentCardComponent extends ContainerBaseComponent {
2626
this.arSecondaryButtons$,
2727
this.actionButtonClick,
2828
]);
29+
this.actionButtonsComponent.init();
2930
this.sendPropsUpdate();
3031
}
3132

scripts/dxcomponents/components/containers/assignment.component.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ export class AssignmentComponent extends BaseComponent {
132132
"AssignmentCard",
133133
assignmentCardArgs
134134
);
135+
this.assignmentCardComponent.init();
135136
this.loading = this.newPConn.getLoadingStatus();
136137
this.sendPropsUpdate();
137138
}

scripts/dxcomponents/components/containers/container-base.component.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export class ContainerBaseComponent extends BaseComponent {
4848
oldChildrenComponents.splice(oldChildrenComponents.indexOf(oldComponentToReuse), 1);
4949
} else {
5050
const newPConn = newChild.getPConnect();
51-
const newChildComponent = this.componentsManager.create(newPConn.meta.type, [newPConn], false);
51+
const newChildComponent = this.componentsManager.create(newPConn.meta.type, [newPConn]);
5252
reconciledComponents.push(newChildComponent);
5353
uninitializedComponents.push(newChildComponent);
5454
}

scripts/dxcomponents/components/containers/flow-container.component.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,11 @@ export class FlowContainerComponent extends BaseComponent {
134134
]
135135
: [];
136136

137-
this.alertBannerComponents = banners.map((b) =>
138-
this.componentsManager.create("AlertBanner", [b.variant, b.messages], true)
139-
);
137+
this.alertBannerComponents = banners.map((b) => {
138+
const component = this.componentsManager.create("AlertBanner", [b.variant, b.messages]);
139+
component.init();
140+
return component;
141+
});
140142
}
141143

142144
#destroyBanners() {
@@ -171,6 +173,7 @@ export class FlowContainerComponent extends BaseComponent {
171173
this.childrenPConns,
172174
this.containerContextKey,
173175
]);
176+
this.assignmentComponent.init();
174177
}
175178

176179
#updateSelf() {

scripts/dxcomponents/components/containers/modal-view-container.component.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,11 @@ export class ModalViewContainerComponent extends ContainerBaseComponent {
256256
]
257257
: [];
258258

259-
this.alertBannerComponents = banners.map((b) =>
260-
this.componentsManager.create("AlertBanner", [b.variant, b.messages], true)
261-
);
259+
this.alertBannerComponents = banners.map((b) => {
260+
const component = this.componentsManager.create("AlertBanner", [b.variant, b.messages]);
261+
component.init();
262+
return component;
263+
});
262264
}
263265

264266
#getBannerMessages() {

scripts/dxcomponents/components/containers/root-container.component.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ export class RootContainerComponent extends BaseComponent {
108108
viewContainerPConn.meta.type,
109109
[viewContainerPConn]
110110
);
111+
this.#viewContainerComponent.init();
111112
}
112113

113114
#configureModalContainer() {
@@ -127,6 +128,7 @@ export class RootContainerComponent extends BaseComponent {
127128
modalViewContainerPConn.meta.type,
128129
[modalViewContainerPConn]
129130
);
131+
this.#modalViewContainerComponent.init();
130132
if (this.compId !== "1") {
131133
console.error(TAG, "RootComponent id must be '1' to match root container on consumer side");
132134
return;

scripts/dxcomponents/components/containers/templates/field-group-template.component.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ export class FieldGroupTemplateComponent extends BaseComponent {
100100
evaluateAllowRowAction(allowRowEdit, item)
101101
).getPConnect();
102102
const newComponent = this.componentsManager.upsert(oldComponent, newPConn.meta.type, [newPConn]);
103+
newComponent.init();
103104
updatedItems.push({
104105
id: index,
105106
name:

scripts/dxcomponents/components/containers/templates/simple-table.component.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,13 @@ export class SimpleTableComponent extends BaseComponent {
7373
this.pConn,
7474
fieldGroupProps,
7575
]);
76+
this.childComponent.init();
7677
this.#sendPropsUpdate();
7778
} else if (fieldMetadata && fieldMetadata.type === 'Page List' && fieldMetadata.dataRetrievalType === 'refer') {
7879
console.warn(TAG, 'Displaying ListView in SimpleTable is not supported yet.');
7980
} else {
8081
this.childComponent = this.componentsManager.upsert(this.childComponent, "SimpleTableManual", [this.pConn]);
82+
this.childComponent.init();
8183
this.#sendPropsUpdate();
8284
}
8385
}

scripts/dxcomponents/components/containers/view-container.component.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ export class ViewContainerComponent extends BaseComponent {
9494
const viewPConn = ReferenceComponent.normalizePConn(newCompPConn);
9595
this.childComponent?.destroy?.();
9696
this.childComponent = this.componentsManager.create(viewPConn.meta.type, [viewPConn]);
97+
this.childComponent.init();
9798
this.props.children = [this.childComponent.compId];
9899
this.componentsManager.onComponentPropsUpdate(this);
99100
}

0 commit comments

Comments
 (0)