Skip to content

Commit 90fc7c6

Browse files
Refine dash.Patch initial call suppression when output prop is unchanged
1 parent 67f74e2 commit 90fc7c6

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
@@ -1243,8 +1243,14 @@ export function getWatchedKeys(id, newProps, graphs) {
12431243
* See getCallbackByOutput for details.
12441244
*/
12451245
export function getUnfilteredLayoutCallbacks(graphs, paths, layoutChunk, opts) {
1246-
const {outputsOnly, removedArrayInputsOnly, newPaths, chunkPath, oldPaths} =
1247-
opts;
1246+
const {
1247+
outputsOnly,
1248+
removedArrayInputsOnly,
1249+
newPaths,
1250+
chunkPath,
1251+
oldPaths,
1252+
oldLayout
1253+
} = opts;
12481254
const foundCbIds = {};
12491255
const callbacks = [];
12501256

@@ -1290,7 +1296,25 @@ export function getUnfilteredLayoutCallbacks(graphs, paths, layoutChunk, opts) {
12901296
});
12911297
}
12921298

1293-
function handleOneId(id, outIdCallbacks, inIdCallbacks) {
1299+
// Suppress initial call only when the component's output prop is unchanged
1300+
// (the component was preserved by a Patch operation). Full-replace
1301+
// returns new component instances whose props are reset to defaults, so their
1302+
// output props will differ from the old layout and the callback must still fire.
1303+
function isUnchangedOutputProp(id, property, child) {
1304+
if (!chunkPath || !oldPaths || !oldLayout) return false;
1305+
const oldPath = getPath(oldPaths, id);
1306+
if (!oldPath) return false;
1307+
const oldPropValue = path([...oldPath, 'props', property], oldLayout);
1308+
// If the prop was never set in the old layout (undefined), we cannot
1309+
// treat it as "unchanged" and the callback must still fire to populate it.
1310+
// This prevents incorrectly suppressing title callbacks and other output
1311+
// props that were undefined in both old and new layouts (undefined === undefined).
1312+
if (oldPropValue === undefined) return false;
1313+
const newPropValue = child ? path(['props', property], child) : undefined;
1314+
return oldPropValue === newPropValue;
1315+
}
1316+
1317+
function handleOneId(id, outIdCallbacks, inIdCallbacks, child) {
12941318
if (outIdCallbacks) {
12951319
for (const property in outIdCallbacks) {
12961320
const cb = getCallbackByOutput(graphs, paths, id, property);
@@ -1299,11 +1323,9 @@ export function getUnfilteredLayoutCallbacks(graphs, paths, layoutChunk, opts) {
12991323
// unless specifically requested not to.
13001324
// ie this is the initial call of this callback even if it's
13011325
// not the page initialization but just a new layout chunk
1302-
// Don't fire initial call for components that already existed before
1303-
// this chunk update (e.g. existing MATCH items when Patch adds a new one).
13041326
if (
13051327
!cb.callback.prevent_initial_call &&
1306-
!(chunkPath && oldPaths && getPath(oldPaths, id))
1328+
!isUnchangedOutputProp(id, property, child)
13071329
) {
13081330
cb.initialCall = true;
13091331
addCallback(cb);
@@ -1344,13 +1366,14 @@ export function getUnfilteredLayoutCallbacks(graphs, paths, layoutChunk, opts) {
13441366
const id = path(['props', 'id'], child);
13451367
if (id) {
13461368
if (typeof id === 'string' && !removedArrayInputsOnly) {
1347-
handleOneId(id, graphs.outputMap[id], graphs.inputMap[id]);
1369+
handleOneId(id, graphs.outputMap[id], graphs.inputMap[id], child);
13481370
} else {
13491371
const keyStr = Object.keys(id).sort().join(',');
13501372
handleOneId(
13511373
id,
13521374
!removedArrayInputsOnly && graphs.outputPatterns[keyStr],
1353-
graphs.inputPatterns[keyStr]
1375+
graphs.inputPatterns[keyStr],
1376+
child
13541377
);
13551378
}
13561379
}

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)