Skip to content

Commit a3ddc4e

Browse files
fix: ensure onChange callback is not called multiple times on site load
Using some state, ensure that the first call of onEntryChange callback only happens from one of - requestDataSync, callback registration or first client-data-send
1 parent a0d3a5d commit a3ddc4e

3 files changed

Lines changed: 57 additions & 18 deletions

File tree

src/livePreview/eventManager/postMessageEvent.hooks.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Config, { setConfigFromParams } from "../../configManager/configManager";
2+
import ContentstackLivePreview from "../../preview/contentstack-live-preview-HOC";
23
import { ILivePreviewWindowType } from "../../types/types";
34
import { addParamsToUrl } from "../../utils";
45
import livePreviewPostMessage from "./livePreviewEventManager";
@@ -51,6 +52,18 @@ export function useOnEntryUpdatePostMessageEvent(): void {
5152
});
5253
const { ssr, onChange } = Config.get();
5354
if (!ssr) {
55+
console.log("onChange called for client-data-send");
56+
// if client-data-send is received for the first time
57+
// and onChange has not been called for the first time, call it
58+
if (!ContentstackLivePreview.hasReceivedFirstClientDataSend) {
59+
ContentstackLivePreview.hasReceivedFirstClientDataSend =
60+
true;
61+
if (!ContentstackLivePreview.firstOnChangeCalled) {
62+
onChange();
63+
ContentstackLivePreview.firstOnChangeCalled = true;
64+
return;
65+
}
66+
}
5467
onChange();
5568
}
5669
}
@@ -79,7 +92,10 @@ export function sendInitializeLivePreviewPostMessageEvent(): void {
7992

8093
// TODO: This is a fix for the issue where we were calling sending init in the builder
8194
// Let's remove this condition when we fix it.
82-
if (Config?.get()?.windowType && Config.get().windowType === ILivePreviewWindowType.BUILDER) {
95+
if (
96+
Config?.get()?.windowType &&
97+
Config.get().windowType === ILivePreviewWindowType.BUILDER
98+
) {
8399
return;
84100
}
85101

src/livePreview/live-preview.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { aC } from "vitest/dist/chunks/reporters.D7Jzd9GS.js";
12
import Config from "../configManager/configManager";
23
import { PublicLogger } from "../logger/logger";
34
import { ILivePreviewModeConfig } from "../types/types";
@@ -12,6 +13,7 @@ import {
1213
OnEntryChangeCallbackUID,
1314
OnEntryChangeUnsubscribeParameters,
1415
} from "./types/onEntryChangeCallback.type";
16+
import ContentstackLivePreview from "../preview/contentstack-live-preview-HOC";
1517

1618
export default class LivePreview {
1719
/**
@@ -53,14 +55,13 @@ export default class LivePreview {
5355
// render the hover outline only when edit button enable
5456

5557
if (
56-
!isOpeningInTimeline() &&
58+
!isOpeningInTimeline() &&
5759
(config.editButton.enable ||
58-
config.mode >= ILivePreviewModeConfig.BUILDER)
60+
config.mode >= ILivePreviewModeConfig.BUILDER)
5961
) {
6062
LivePreviewEditButton.livePreviewEditButton =
6163
new LivePreviewEditButton();
6264
}
63-
6465
} else if (config.cleanCslpOnProduction) {
6566
removeDataCslp();
6667
}
@@ -74,7 +75,10 @@ export default class LivePreview {
7475

7576
//! TODO: we replaced the handleOnChange() with this.
7677
//! I don't think we need this. Confirm and remove it.
77-
config.onChange();
78+
if (!ContentstackLivePreview.firstOnChangeCalled) {
79+
console.log("Requesting data sync");
80+
config.onChange();
81+
}
7882

7983
sendInitializeLivePreviewPostMessageEvent();
8084
}
@@ -88,8 +92,10 @@ export default class LivePreview {
8892
}
8993

9094
private publish(): void {
95+
console.log("Calling callbacks", this.subscribers);
9196
Object.values<OnEntryChangeCallback>(this.subscribers).forEach(
9297
(func) => {
98+
console.log("Calling subscriber", func);
9399
func();
94100
}
95101
);

src/preview/contentstack-live-preview-HOC.ts

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ class ContentstackLivePreview {
3131
private static onEntryChangeCallbacks: OnEntryChangeCallbackSubscribers =
3232
{};
3333

34+
/**
35+
* Tracks whether the first onChange has been called.
36+
*/
37+
static firstOnChangeCalled: boolean = false;
38+
/**
39+
* Tracks whether the first client-data-send has been received.
40+
*/
41+
static hasReceivedFirstClientDataSend: boolean = false;
42+
3443
/**
3544
* Initializes the Live Preview SDK with the provided user configuration.
3645
* If the SDK is already initialized, subsequent calls to this method will return the existing SDK instance.
@@ -77,15 +86,15 @@ class ContentstackLivePreview {
7786
const config = Config.get();
7887
const clonedConfig = cloneDeep(config);
7988
const configToShare = pick(clonedConfig, [
80-
'ssr',
81-
'enable',
82-
'cleanCslpOnProduction',
83-
'stackDetails',
84-
'clientUrlParams',
85-
'windowType',
86-
'hash',
87-
'editButton',
88-
'mode',
89+
"ssr",
90+
"enable",
91+
"cleanCslpOnProduction",
92+
"stackDetails",
93+
"clientUrlParams",
94+
"windowType",
95+
"hash",
96+
"editButton",
97+
"mode",
8998
]);
9099
return configToShare;
91100
}
@@ -153,14 +162,21 @@ class ContentstackLivePreview {
153162
}
154163

155164
const isWindowDefined = typeof window !== "undefined";
165+
const searchParams =
166+
isWindowDefined && new URLSearchParams(window.location.search);
156167
const isLivePreviewSearchParamPresent =
157-
isWindowDefined &&
158-
new URLSearchParams(window.location.search).has("live_preview");
168+
searchParams && searchParams.has("live_preview");
169+
const shouldCallCallback =
170+
skipInitialRender && isLivePreviewSearchParamPresent;
159171
// calling onChangeCallback when live_preview search parameter
160172
// is present because we don't send the initial client-data-send
161173
// message in visual builder
162-
if (!skipInitialRender || isLivePreviewSearchParamPresent) {
174+
if (
175+
!skipInitialRender ||
176+
(shouldCallCallback && !this.firstOnChangeCalled)
177+
) {
163178
onChangeCallback();
179+
ContentstackLivePreview.firstOnChangeCalled = true;
164180
}
165181

166182
return callbackUid;
@@ -185,6 +201,7 @@ class ContentstackLivePreview {
185201
static onLiveEdit(
186202
onChangeCallback: OnEntryChangeCallback
187203
): OnEntryChangeCallbackUID {
204+
console.log("Requesting onLiveEdit");
188205
return ContentstackLivePreview.onEntryChange(onChangeCallback, {
189206
skipInitialRender: true,
190207
});
@@ -252,4 +269,4 @@ class ContentstackLivePreview {
252269
}
253270
}
254271

255-
export default ContentstackLivePreview;
272+
export default ContentstackLivePreview;

0 commit comments

Comments
 (0)