Skip to content

Commit 68566a7

Browse files
Refine dash.Patch initial call suppression when output prop is unchanged
1 parent 79a63be commit 68566a7

File tree

2 files changed

+32
-8
lines changed

2 files changed

+32
-8
lines changed

dash/dash-renderer/src/actions/dependencies.js

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,8 +1194,14 @@ export function getWatchedKeys(id, newProps, graphs) {
11941194
* See getCallbackByOutput for details.
11951195
*/
11961196
export function getUnfilteredLayoutCallbacks(graphs, paths, layoutChunk, opts) {
1197-
const {outputsOnly, removedArrayInputsOnly, newPaths, chunkPath, oldPaths} =
1198-
opts;
1197+
const {
1198+
outputsOnly,
1199+
removedArrayInputsOnly,
1200+
newPaths,
1201+
chunkPath,
1202+
oldPaths,
1203+
oldLayout
1204+
} = opts;
11991205
const foundCbIds = {};
12001206
const callbacks = [];
12011207

@@ -1241,7 +1247,25 @@ export function getUnfilteredLayoutCallbacks(graphs, paths, layoutChunk, opts) {
12411247
});
12421248
}
12431249

1244-
function handleOneId(id, outIdCallbacks, inIdCallbacks) {
1250+
// Suppress initial call only when the component's output prop is unchanged
1251+
// (the component was preserved by a Patch operation). Full-replace
1252+
// returns new component instances whose props are reset to defaults, so their
1253+
// output props will differ from the old layout and the callback must still fire.
1254+
function isUnchangedOutputProp(id, property, child) {
1255+
if (!chunkPath || !oldPaths || !oldLayout) return false;
1256+
const oldPath = getPath(oldPaths, id);
1257+
if (!oldPath) return false;
1258+
const oldPropValue = path([...oldPath, 'props', property], oldLayout);
1259+
// If the prop was never set in the old layout (undefined), we cannot
1260+
// treat it as "unchanged" and the callback must still fire to populate it.
1261+
// This prevents incorrectly suppressing title callbacks and other output
1262+
// props that were undefined in both old and new layouts (undefined === undefined).
1263+
if (oldPropValue === undefined) return false;
1264+
const newPropValue = child ? path(['props', property], child) : undefined;
1265+
return oldPropValue === newPropValue;
1266+
}
1267+
1268+
function handleOneId(id, outIdCallbacks, inIdCallbacks, child) {
12451269
if (outIdCallbacks) {
12461270
for (const property in outIdCallbacks) {
12471271
const cb = getCallbackByOutput(graphs, paths, id, property);
@@ -1250,11 +1274,9 @@ export function getUnfilteredLayoutCallbacks(graphs, paths, layoutChunk, opts) {
12501274
// unless specifically requested not to.
12511275
// ie this is the initial call of this callback even if it's
12521276
// not the page initialization but just a new layout chunk
1253-
// Don't fire initial call for components that already existed before
1254-
// this chunk update (e.g. existing MATCH items when Patch adds a new one).
12551277
if (
12561278
!cb.callback.prevent_initial_call &&
1257-
!(chunkPath && oldPaths && getPath(oldPaths, id))
1279+
!isUnchangedOutputProp(id, property, child)
12581280
) {
12591281
cb.initialCall = true;
12601282
addCallback(cb);
@@ -1295,13 +1317,14 @@ export function getUnfilteredLayoutCallbacks(graphs, paths, layoutChunk, opts) {
12951317
const id = path(['props', 'id'], child);
12961318
if (id) {
12971319
if (typeof id === 'string' && !removedArrayInputsOnly) {
1298-
handleOneId(id, graphs.outputMap[id], graphs.inputMap[id]);
1320+
handleOneId(id, graphs.outputMap[id], graphs.inputMap[id], child);
12991321
} else {
13001322
const keyStr = Object.keys(id).sort().join(',');
13011323
handleOneId(
13021324
id,
13031325
!removedArrayInputsOnly && graphs.outputPatterns[keyStr],
1304-
graphs.inputPatterns[keyStr]
1326+
graphs.inputPatterns[keyStr],
1327+
child
13051328
);
13061329
}
13071330
}

dash/dash-renderer/src/observers/executedCallbacks.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ const observer: IStoreObserverDefinition<IStoreState> = {
161161
getLayoutCallbacks(graphs, paths, children, {
162162
chunkPath: oldChildrenPath,
163163
oldPaths: oPaths,
164+
oldLayout: oldLayout,
164165
filterRoot
165166
}).map(rcb => ({
166167
...rcb,

0 commit comments

Comments
 (0)