[devtools] fix: check if profiling for all profiling hooks (#33701)

Follow-up to https://github.com/facebook/react/pull/33652.

Don't know how the other were missed. Double-checked that Profiler works
in dev mode.

Now all hooks start with `!isProfiling` check and return, if true.
This commit is contained in:
Ruslan Lesiutin 2025-07-04 16:21:51 +01:00 committed by GitHub
parent 455424dbf3
commit 5f71eed2eb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -298,14 +298,16 @@ export function createProfilingHooks({
} }
function markCommitStarted(lanes: Lanes): void { function markCommitStarted(lanes: Lanes): void {
if (isProfiling) { if (!isProfiling) {
recordReactMeasureStarted('commit', lanes); return;
// TODO (timeline) Re-think this approach to "batching"; I don't think it works for Suspense or pre-rendering.
// This issue applies to the User Timing data also.
nextRenderShouldStartNewBatch = true;
} }
recordReactMeasureStarted('commit', lanes);
// TODO (timeline) Re-think this approach to "batching"; I don't think it works for Suspense or pre-rendering.
// This issue applies to the User Timing data also.
nextRenderShouldStartNewBatch = true;
if (supportsUserTimingV3) { if (supportsUserTimingV3) {
markAndClear(`--commit-start-${lanes}`); markAndClear(`--commit-start-${lanes}`);
@ -318,50 +320,55 @@ export function createProfilingHooks({
} }
function markCommitStopped(): void { function markCommitStopped(): void {
if (isProfiling) { if (!isProfiling) {
recordReactMeasureCompleted('commit'); return;
recordReactMeasureCompleted('render-idle');
} }
recordReactMeasureCompleted('commit');
recordReactMeasureCompleted('render-idle');
if (supportsUserTimingV3) { if (supportsUserTimingV3) {
markAndClear('--commit-stop'); markAndClear('--commit-stop');
} }
} }
function markComponentRenderStarted(fiber: Fiber): void { function markComponentRenderStarted(fiber: Fiber): void {
if (isProfiling) { if (!isProfiling) {
const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; return;
}
// TODO (timeline) Record and cache component stack const componentName = getDisplayNameForFiber(fiber) || 'Unknown';
currentReactComponentMeasure = {
componentName,
duration: 0,
timestamp: getRelativeTime(),
type: 'render',
warning: null,
};
if (supportsUserTimingV3) { // TODO (timeline) Record and cache component stack
markAndClear(`--component-render-start-${componentName}`); currentReactComponentMeasure = {
} componentName,
duration: 0,
timestamp: getRelativeTime(),
type: 'render',
warning: null,
};
if (supportsUserTimingV3) {
markAndClear(`--component-render-start-${componentName}`);
} }
} }
function markComponentRenderStopped(): void { function markComponentRenderStopped(): void {
if (isProfiling) { if (!isProfiling) {
if (currentReactComponentMeasure) { return;
if (currentTimelineData) { }
currentTimelineData.componentMeasures.push(
currentReactComponentMeasure,
);
}
// $FlowFixMe[incompatible-use] found when upgrading Flow if (currentReactComponentMeasure) {
currentReactComponentMeasure.duration = if (currentTimelineData) {
// $FlowFixMe[incompatible-use] found when upgrading Flow currentTimelineData.componentMeasures.push(
getRelativeTime() - currentReactComponentMeasure.timestamp; currentReactComponentMeasure,
currentReactComponentMeasure = null; );
} }
// $FlowFixMe[incompatible-use] found when upgrading Flow
currentReactComponentMeasure.duration =
// $FlowFixMe[incompatible-use] found when upgrading Flow
getRelativeTime() - currentReactComponentMeasure.timestamp;
currentReactComponentMeasure = null;
} }
if (supportsUserTimingV3) { if (supportsUserTimingV3) {
@ -370,39 +377,43 @@ export function createProfilingHooks({
} }
function markComponentLayoutEffectMountStarted(fiber: Fiber): void { function markComponentLayoutEffectMountStarted(fiber: Fiber): void {
if (isProfiling) { if (!isProfiling) {
const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; return;
}
// TODO (timeline) Record and cache component stack const componentName = getDisplayNameForFiber(fiber) || 'Unknown';
currentReactComponentMeasure = {
componentName,
duration: 0,
timestamp: getRelativeTime(),
type: 'layout-effect-mount',
warning: null,
};
if (supportsUserTimingV3) { // TODO (timeline) Record and cache component stack
markAndClear(`--component-layout-effect-mount-start-${componentName}`); currentReactComponentMeasure = {
} componentName,
duration: 0,
timestamp: getRelativeTime(),
type: 'layout-effect-mount',
warning: null,
};
if (supportsUserTimingV3) {
markAndClear(`--component-layout-effect-mount-start-${componentName}`);
} }
} }
function markComponentLayoutEffectMountStopped(): void { function markComponentLayoutEffectMountStopped(): void {
if (isProfiling) { if (!isProfiling) {
if (currentReactComponentMeasure) { return;
if (currentTimelineData) { }
currentTimelineData.componentMeasures.push(
currentReactComponentMeasure,
);
}
// $FlowFixMe[incompatible-use] found when upgrading Flow if (currentReactComponentMeasure) {
currentReactComponentMeasure.duration = if (currentTimelineData) {
// $FlowFixMe[incompatible-use] found when upgrading Flow currentTimelineData.componentMeasures.push(
getRelativeTime() - currentReactComponentMeasure.timestamp; currentReactComponentMeasure,
currentReactComponentMeasure = null; );
} }
// $FlowFixMe[incompatible-use] found when upgrading Flow
currentReactComponentMeasure.duration =
// $FlowFixMe[incompatible-use] found when upgrading Flow
getRelativeTime() - currentReactComponentMeasure.timestamp;
currentReactComponentMeasure = null;
} }
if (supportsUserTimingV3) { if (supportsUserTimingV3) {
@ -411,41 +422,43 @@ export function createProfilingHooks({
} }
function markComponentLayoutEffectUnmountStarted(fiber: Fiber): void { function markComponentLayoutEffectUnmountStarted(fiber: Fiber): void {
if (isProfiling) { if (!isProfiling) {
const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; return;
}
// TODO (timeline) Record and cache component stack const componentName = getDisplayNameForFiber(fiber) || 'Unknown';
currentReactComponentMeasure = {
componentName,
duration: 0,
timestamp: getRelativeTime(),
type: 'layout-effect-unmount',
warning: null,
};
if (supportsUserTimingV3) { // TODO (timeline) Record and cache component stack
markAndClear( currentReactComponentMeasure = {
`--component-layout-effect-unmount-start-${componentName}`, componentName,
); duration: 0,
} timestamp: getRelativeTime(),
type: 'layout-effect-unmount',
warning: null,
};
if (supportsUserTimingV3) {
markAndClear(`--component-layout-effect-unmount-start-${componentName}`);
} }
} }
function markComponentLayoutEffectUnmountStopped(): void { function markComponentLayoutEffectUnmountStopped(): void {
if (isProfiling) { if (!isProfiling) {
if (currentReactComponentMeasure) { return;
if (currentTimelineData) { }
currentTimelineData.componentMeasures.push(
currentReactComponentMeasure,
);
}
// $FlowFixMe[incompatible-use] found when upgrading Flow if (currentReactComponentMeasure) {
currentReactComponentMeasure.duration = if (currentTimelineData) {
// $FlowFixMe[incompatible-use] found when upgrading Flow currentTimelineData.componentMeasures.push(
getRelativeTime() - currentReactComponentMeasure.timestamp; currentReactComponentMeasure,
currentReactComponentMeasure = null; );
} }
// $FlowFixMe[incompatible-use] found when upgrading Flow
currentReactComponentMeasure.duration =
// $FlowFixMe[incompatible-use] found when upgrading Flow
getRelativeTime() - currentReactComponentMeasure.timestamp;
currentReactComponentMeasure = null;
} }
if (supportsUserTimingV3) { if (supportsUserTimingV3) {
@ -454,39 +467,43 @@ export function createProfilingHooks({
} }
function markComponentPassiveEffectMountStarted(fiber: Fiber): void { function markComponentPassiveEffectMountStarted(fiber: Fiber): void {
if (isProfiling) { if (!isProfiling) {
const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; return;
}
// TODO (timeline) Record and cache component stack const componentName = getDisplayNameForFiber(fiber) || 'Unknown';
currentReactComponentMeasure = {
componentName,
duration: 0,
timestamp: getRelativeTime(),
type: 'passive-effect-mount',
warning: null,
};
if (supportsUserTimingV3) { // TODO (timeline) Record and cache component stack
markAndClear(`--component-passive-effect-mount-start-${componentName}`); currentReactComponentMeasure = {
} componentName,
duration: 0,
timestamp: getRelativeTime(),
type: 'passive-effect-mount',
warning: null,
};
if (supportsUserTimingV3) {
markAndClear(`--component-passive-effect-mount-start-${componentName}`);
} }
} }
function markComponentPassiveEffectMountStopped(): void { function markComponentPassiveEffectMountStopped(): void {
if (isProfiling) { if (!isProfiling) {
if (currentReactComponentMeasure) { return;
if (currentTimelineData) { }
currentTimelineData.componentMeasures.push(
currentReactComponentMeasure,
);
}
// $FlowFixMe[incompatible-use] found when upgrading Flow if (currentReactComponentMeasure) {
currentReactComponentMeasure.duration = if (currentTimelineData) {
// $FlowFixMe[incompatible-use] found when upgrading Flow currentTimelineData.componentMeasures.push(
getRelativeTime() - currentReactComponentMeasure.timestamp; currentReactComponentMeasure,
currentReactComponentMeasure = null; );
} }
// $FlowFixMe[incompatible-use] found when upgrading Flow
currentReactComponentMeasure.duration =
// $FlowFixMe[incompatible-use] found when upgrading Flow
getRelativeTime() - currentReactComponentMeasure.timestamp;
currentReactComponentMeasure = null;
} }
if (supportsUserTimingV3) { if (supportsUserTimingV3) {
@ -495,41 +512,43 @@ export function createProfilingHooks({
} }
function markComponentPassiveEffectUnmountStarted(fiber: Fiber): void { function markComponentPassiveEffectUnmountStarted(fiber: Fiber): void {
if (isProfiling) { if (!isProfiling) {
const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; return;
}
// TODO (timeline) Record and cache component stack const componentName = getDisplayNameForFiber(fiber) || 'Unknown';
currentReactComponentMeasure = {
componentName,
duration: 0,
timestamp: getRelativeTime(),
type: 'passive-effect-unmount',
warning: null,
};
if (supportsUserTimingV3) { // TODO (timeline) Record and cache component stack
markAndClear( currentReactComponentMeasure = {
`--component-passive-effect-unmount-start-${componentName}`, componentName,
); duration: 0,
} timestamp: getRelativeTime(),
type: 'passive-effect-unmount',
warning: null,
};
if (supportsUserTimingV3) {
markAndClear(`--component-passive-effect-unmount-start-${componentName}`);
} }
} }
function markComponentPassiveEffectUnmountStopped(): void { function markComponentPassiveEffectUnmountStopped(): void {
if (isProfiling) { if (!isProfiling) {
if (currentReactComponentMeasure) { return;
if (currentTimelineData) { }
currentTimelineData.componentMeasures.push(
currentReactComponentMeasure,
);
}
// $FlowFixMe[incompatible-use] found when upgrading Flow if (currentReactComponentMeasure) {
currentReactComponentMeasure.duration = if (currentTimelineData) {
// $FlowFixMe[incompatible-use] found when upgrading Flow currentTimelineData.componentMeasures.push(
getRelativeTime() - currentReactComponentMeasure.timestamp; currentReactComponentMeasure,
currentReactComponentMeasure = null; );
} }
// $FlowFixMe[incompatible-use] found when upgrading Flow
currentReactComponentMeasure.duration =
// $FlowFixMe[incompatible-use] found when upgrading Flow
getRelativeTime() - currentReactComponentMeasure.timestamp;
currentReactComponentMeasure = null;
} }
if (supportsUserTimingV3) { if (supportsUserTimingV3) {
@ -542,35 +561,37 @@ export function createProfilingHooks({
thrownValue: mixed, thrownValue: mixed,
lanes: Lanes, lanes: Lanes,
): void { ): void {
if (isProfiling) { if (!isProfiling) {
const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; return;
const phase = fiber.alternate === null ? 'mount' : 'update'; }
let message = ''; const componentName = getDisplayNameForFiber(fiber) || 'Unknown';
if ( const phase = fiber.alternate === null ? 'mount' : 'update';
thrownValue !== null &&
typeof thrownValue === 'object' &&
typeof thrownValue.message === 'string'
) {
message = thrownValue.message;
} else if (typeof thrownValue === 'string') {
message = thrownValue;
}
// TODO (timeline) Record and cache component stack let message = '';
if (currentTimelineData) { if (
currentTimelineData.thrownErrors.push({ thrownValue !== null &&
componentName, typeof thrownValue === 'object' &&
message, typeof thrownValue.message === 'string'
phase, ) {
timestamp: getRelativeTime(), message = thrownValue.message;
type: 'thrown-error', } else if (typeof thrownValue === 'string') {
}); message = thrownValue;
} }
if (supportsUserTimingV3) { // TODO (timeline) Record and cache component stack
markAndClear(`--error-${componentName}-${phase}-${message}`); if (currentTimelineData) {
} currentTimelineData.thrownErrors.push({
componentName,
message,
phase,
timestamp: getRelativeTime(),
type: 'thrown-error',
});
}
if (supportsUserTimingV3) {
markAndClear(`--error-${componentName}-${phase}-${message}`);
} }
} }
@ -591,165 +612,176 @@ export function createProfilingHooks({
wakeable: Wakeable, wakeable: Wakeable,
lanes: Lanes, lanes: Lanes,
): void { ): void {
if (isProfiling) { if (!isProfiling) {
const eventType = wakeableIDs.has(wakeable) ? 'resuspend' : 'suspend'; return;
const id = getWakeableID(wakeable); }
const componentName = getDisplayNameForFiber(fiber) || 'Unknown';
const phase = fiber.alternate === null ? 'mount' : 'update';
// Following the non-standard fn.displayName convention, const eventType = wakeableIDs.has(wakeable) ? 'resuspend' : 'suspend';
// frameworks like Relay may also annotate Promises with a displayName, const id = getWakeableID(wakeable);
// describing what operation/data the thrown Promise is related to. const componentName = getDisplayNameForFiber(fiber) || 'Unknown';
// When this is available we should pass it along to the Timeline. const phase = fiber.alternate === null ? 'mount' : 'update';
const displayName = (wakeable: any).displayName || '';
let suspenseEvent: SuspenseEvent | null = null; // Following the non-standard fn.displayName convention,
// TODO (timeline) Record and cache component stack // frameworks like Relay may also annotate Promises with a displayName,
suspenseEvent = { // describing what operation/data the thrown Promise is related to.
componentName, // When this is available we should pass it along to the Timeline.
depth: 0, const displayName = (wakeable: any).displayName || '';
duration: 0,
id: `${id}`,
phase,
promiseName: displayName,
resolution: 'unresolved',
timestamp: getRelativeTime(),
type: 'suspense',
warning: null,
};
if (currentTimelineData) { let suspenseEvent: SuspenseEvent | null = null;
currentTimelineData.suspenseEvents.push(suspenseEvent); // TODO (timeline) Record and cache component stack
} suspenseEvent = {
componentName,
depth: 0,
duration: 0,
id: `${id}`,
phase,
promiseName: displayName,
resolution: 'unresolved',
timestamp: getRelativeTime(),
type: 'suspense',
warning: null,
};
if (supportsUserTimingV3) { if (currentTimelineData) {
markAndClear( currentTimelineData.suspenseEvents.push(suspenseEvent);
`--suspense-${eventType}-${id}-${componentName}-${phase}-${lanes}-${displayName}`, }
);
wakeable.then( if (supportsUserTimingV3) {
() => { markAndClear(
if (suspenseEvent) { `--suspense-${eventType}-${id}-${componentName}-${phase}-${lanes}-${displayName}`,
suspenseEvent.duration = );
getRelativeTime() - suspenseEvent.timestamp;
suspenseEvent.resolution = 'resolved';
}
if (supportsUserTimingV3) { wakeable.then(
markAndClear(`--suspense-resolved-${id}-${componentName}`); () => {
} if (suspenseEvent) {
}, suspenseEvent.duration =
() => { getRelativeTime() - suspenseEvent.timestamp;
if (suspenseEvent) { suspenseEvent.resolution = 'resolved';
suspenseEvent.duration = }
getRelativeTime() - suspenseEvent.timestamp;
suspenseEvent.resolution = 'rejected';
}
if (supportsUserTimingV3) { if (supportsUserTimingV3) {
markAndClear(`--suspense-rejected-${id}-${componentName}`); markAndClear(`--suspense-resolved-${id}-${componentName}`);
} }
}, },
); () => {
} if (suspenseEvent) {
suspenseEvent.duration =
getRelativeTime() - suspenseEvent.timestamp;
suspenseEvent.resolution = 'rejected';
}
if (supportsUserTimingV3) {
markAndClear(`--suspense-rejected-${id}-${componentName}`);
}
},
);
} }
} }
function markLayoutEffectsStarted(lanes: Lanes): void { function markLayoutEffectsStarted(lanes: Lanes): void {
if (isProfiling) { if (!isProfiling) {
recordReactMeasureStarted('layout-effects', lanes); return;
} }
recordReactMeasureStarted('layout-effects', lanes);
if (supportsUserTimingV3) { if (supportsUserTimingV3) {
markAndClear(`--layout-effects-start-${lanes}`); markAndClear(`--layout-effects-start-${lanes}`);
} }
} }
function markLayoutEffectsStopped(): void { function markLayoutEffectsStopped(): void {
if (isProfiling) { if (!isProfiling) {
recordReactMeasureCompleted('layout-effects'); return;
} }
recordReactMeasureCompleted('layout-effects');
if (supportsUserTimingV3) { if (supportsUserTimingV3) {
markAndClear('--layout-effects-stop'); markAndClear('--layout-effects-stop');
} }
} }
function markPassiveEffectsStarted(lanes: Lanes): void { function markPassiveEffectsStarted(lanes: Lanes): void {
if (isProfiling) { if (!isProfiling) {
recordReactMeasureStarted('passive-effects', lanes); return;
} }
recordReactMeasureStarted('passive-effects', lanes);
if (supportsUserTimingV3) { if (supportsUserTimingV3) {
markAndClear(`--passive-effects-start-${lanes}`); markAndClear(`--passive-effects-start-${lanes}`);
} }
} }
function markPassiveEffectsStopped(): void { function markPassiveEffectsStopped(): void {
if (isProfiling) { if (!isProfiling) {
recordReactMeasureCompleted('passive-effects'); return;
} }
recordReactMeasureCompleted('passive-effects');
if (supportsUserTimingV3) { if (supportsUserTimingV3) {
markAndClear('--passive-effects-stop'); markAndClear('--passive-effects-stop');
} }
} }
function markRenderStarted(lanes: Lanes): void { function markRenderStarted(lanes: Lanes): void {
if (isProfiling) { if (!isProfiling) {
if (nextRenderShouldStartNewBatch) { return;
nextRenderShouldStartNewBatch = false;
currentBatchUID++;
}
// If this is a new batch of work, wrap an "idle" measure around it.
// Log it before the "render" measure to preserve the stack ordering.
if (
currentReactMeasuresStack.length === 0 ||
currentReactMeasuresStack[currentReactMeasuresStack.length - 1].type !==
'render-idle'
) {
recordReactMeasureStarted('render-idle', lanes);
}
recordReactMeasureStarted('render', lanes);
} }
if (nextRenderShouldStartNewBatch) {
nextRenderShouldStartNewBatch = false;
currentBatchUID++;
}
// If this is a new batch of work, wrap an "idle" measure around it.
// Log it before the "render" measure to preserve the stack ordering.
if (
currentReactMeasuresStack.length === 0 ||
currentReactMeasuresStack[currentReactMeasuresStack.length - 1].type !==
'render-idle'
) {
recordReactMeasureStarted('render-idle', lanes);
}
recordReactMeasureStarted('render', lanes);
if (supportsUserTimingV3) { if (supportsUserTimingV3) {
markAndClear(`--render-start-${lanes}`); markAndClear(`--render-start-${lanes}`);
} }
} }
function markRenderYielded(): void { function markRenderYielded(): void {
if (isProfiling) { if (!isProfiling) {
recordReactMeasureCompleted('render'); return;
} }
recordReactMeasureCompleted('render');
if (supportsUserTimingV3) { if (supportsUserTimingV3) {
markAndClear('--render-yield'); markAndClear('--render-yield');
} }
} }
function markRenderStopped(): void { function markRenderStopped(): void {
if (isProfiling) { if (!isProfiling) {
recordReactMeasureCompleted('render'); return;
} }
recordReactMeasureCompleted('render');
if (supportsUserTimingV3) { if (supportsUserTimingV3) {
markAndClear('--render-stop'); markAndClear('--render-stop');
} }
} }
function markRenderScheduled(lane: Lane): void { function markRenderScheduled(lane: Lane): void {
if (isProfiling) { if (!isProfiling) {
if (currentTimelineData) { return;
currentTimelineData.schedulingEvents.push({ }
lanes: laneToLanesArray(lane),
timestamp: getRelativeTime(), if (currentTimelineData) {
type: 'schedule-render', currentTimelineData.schedulingEvents.push({
warning: null, lanes: laneToLanesArray(lane),
}); timestamp: getRelativeTime(),
} type: 'schedule-render',
warning: null,
});
} }
if (supportsUserTimingV3) { if (supportsUserTimingV3) {
@ -758,23 +790,25 @@ export function createProfilingHooks({
} }
function markForceUpdateScheduled(fiber: Fiber, lane: Lane): void { function markForceUpdateScheduled(fiber: Fiber, lane: Lane): void {
if (isProfiling) { if (!isProfiling) {
const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; return;
}
// TODO (timeline) Record and cache component stack const componentName = getDisplayNameForFiber(fiber) || 'Unknown';
if (currentTimelineData) {
currentTimelineData.schedulingEvents.push({
componentName,
lanes: laneToLanesArray(lane),
timestamp: getRelativeTime(),
type: 'schedule-force-update',
warning: null,
});
}
if (supportsUserTimingV3) { // TODO (timeline) Record and cache component stack
markAndClear(`--schedule-forced-update-${lane}-${componentName}`); if (currentTimelineData) {
} currentTimelineData.schedulingEvents.push({
componentName,
lanes: laneToLanesArray(lane),
timestamp: getRelativeTime(),
type: 'schedule-force-update',
warning: null,
});
}
if (supportsUserTimingV3) {
markAndClear(`--schedule-forced-update-${lane}-${componentName}`);
} }
} }
@ -789,28 +823,30 @@ export function createProfilingHooks({
} }
function markStateUpdateScheduled(fiber: Fiber, lane: Lane): void { function markStateUpdateScheduled(fiber: Fiber, lane: Lane): void {
if (isProfiling) { if (!isProfiling) {
const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; return;
}
// TODO (timeline) Record and cache component stack const componentName = getDisplayNameForFiber(fiber) || 'Unknown';
if (currentTimelineData) {
const event: ReactScheduleStateUpdateEvent = {
componentName,
// Store the parent fibers so we can post process
// them after we finish profiling
lanes: laneToLanesArray(lane),
timestamp: getRelativeTime(),
type: 'schedule-state-update',
warning: null,
};
currentFiberStacks.set(event, getParentFibers(fiber));
// $FlowFixMe[incompatible-use] found when upgrading Flow
currentTimelineData.schedulingEvents.push(event);
}
if (supportsUserTimingV3) { // TODO (timeline) Record and cache component stack
markAndClear(`--schedule-state-update-${lane}-${componentName}`); if (currentTimelineData) {
} const event: ReactScheduleStateUpdateEvent = {
componentName,
// Store the parent fibers so we can post process
// them after we finish profiling
lanes: laneToLanesArray(lane),
timestamp: getRelativeTime(),
type: 'schedule-state-update',
warning: null,
};
currentFiberStacks.set(event, getParentFibers(fiber));
// $FlowFixMe[incompatible-use] found when upgrading Flow
currentTimelineData.schedulingEvents.push(event);
}
if (supportsUserTimingV3) {
markAndClear(`--schedule-state-update-${lane}-${componentName}`);
} }
} }