Skip to content

Commit cfabdb3

Browse files
committed
Add optional initialValue argument to useDeferredValue (#27500)
Adds a second argument to useDeferredValue called initialValue: ```js const value = useDeferredValue(finalValue, initialValue); ``` During the initial render of a component, useDeferredValue will return initialValue. Once that render finishes, it will spawn an additional render to switch to finalValue. This same sequence should occur whenever the hook is hidden and revealed again, i.e. by a Suspense or Activity, though this part is not yet implemented. When initialValue is not provided, useDeferredValue has no effect during initial render, but during an update, it will remain on the previous value, then spawn an additional render to switch to the new value. (This is the same behavior that exists today.) During SSR, initialValue is always used, if provided. This feature is currently behind an experimental flag. We plan to ship it in a non-breaking release. DiffTrain build for [be67db4](be67db4)
1 parent 47d4c42 commit cfabdb3

29 files changed

+679
-311
lines changed

compiled/facebook-www/REVISION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
151e75a128d0fd436dce365335b96c5686f704d4
1+
be67db46b60d94f9fbefccf2523429af25873e5b

compiled/facebook-www/React-dev.classic.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ if (
2727
}
2828
"use strict";
2929

30-
var ReactVersion = "18.3.0-www-classic-f4ae0982";
30+
var ReactVersion = "18.3.0-www-classic-5bedd128";
3131

3232
// ATTENTION
3333
// When adding new symbols to this file,
@@ -1986,9 +1986,9 @@ function useTransition() {
19861986
var dispatcher = resolveDispatcher();
19871987
return dispatcher.useTransition();
19881988
}
1989-
function useDeferredValue(value) {
1989+
function useDeferredValue(value, initialValue) {
19901990
var dispatcher = resolveDispatcher();
1991-
return dispatcher.useDeferredValue(value);
1991+
return dispatcher.useDeferredValue(value, initialValue);
19921992
}
19931993
function useId() {
19941994
var dispatcher = resolveDispatcher();

compiled/facebook-www/React-dev.modern.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ if (
2727
}
2828
"use strict";
2929

30-
var ReactVersion = "18.3.0-www-modern-06b61106";
30+
var ReactVersion = "18.3.0-www-modern-6dbff8b1";
3131

3232
// ATTENTION
3333
// When adding new symbols to this file,
@@ -1986,9 +1986,9 @@ function useTransition() {
19861986
var dispatcher = resolveDispatcher();
19871987
return dispatcher.useTransition();
19881988
}
1989-
function useDeferredValue(value) {
1989+
function useDeferredValue(value, initialValue) {
19901990
var dispatcher = resolveDispatcher();
1991-
return dispatcher.useDeferredValue(value);
1991+
return dispatcher.useDeferredValue(value, initialValue);
19921992
}
19931993
function useId() {
19941994
var dispatcher = resolveDispatcher();

compiled/facebook-www/React-prod.classic.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -576,8 +576,8 @@ exports.useContext = function (Context) {
576576
return ReactCurrentDispatcher.current.useContext(Context);
577577
};
578578
exports.useDebugValue = function () {};
579-
exports.useDeferredValue = function (value) {
580-
return ReactCurrentDispatcher.current.useDeferredValue(value);
579+
exports.useDeferredValue = function (value, initialValue) {
580+
return ReactCurrentDispatcher.current.useDeferredValue(value, initialValue);
581581
};
582582
exports.useEffect = function (create, deps) {
583583
return ReactCurrentDispatcher.current.useEffect(create, deps);
@@ -623,4 +623,4 @@ exports.useSyncExternalStore = function (
623623
exports.useTransition = function () {
624624
return ReactCurrentDispatcher.current.useTransition();
625625
};
626-
exports.version = "18.3.0-www-classic-b08870f0";
626+
exports.version = "18.3.0-www-classic-20c4b7b9";

compiled/facebook-www/React-prod.modern.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -568,8 +568,8 @@ exports.useContext = function (Context) {
568568
return ReactCurrentDispatcher.current.useContext(Context);
569569
};
570570
exports.useDebugValue = function () {};
571-
exports.useDeferredValue = function (value) {
572-
return ReactCurrentDispatcher.current.useDeferredValue(value);
571+
exports.useDeferredValue = function (value, initialValue) {
572+
return ReactCurrentDispatcher.current.useDeferredValue(value, initialValue);
573573
};
574574
exports.useEffect = function (create, deps) {
575575
return ReactCurrentDispatcher.current.useEffect(create, deps);
@@ -615,4 +615,4 @@ exports.useSyncExternalStore = function (
615615
exports.useTransition = function () {
616616
return ReactCurrentDispatcher.current.useTransition();
617617
};
618-
exports.version = "18.3.0-www-modern-20e3e48a";
618+
exports.version = "18.3.0-www-modern-1eaea04e";

compiled/facebook-www/React-profiling.classic.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -587,8 +587,8 @@ exports.useContext = function (Context) {
587587
return ReactCurrentDispatcher.current.useContext(Context);
588588
};
589589
exports.useDebugValue = function () {};
590-
exports.useDeferredValue = function (value) {
591-
return ReactCurrentDispatcher.current.useDeferredValue(value);
590+
exports.useDeferredValue = function (value, initialValue) {
591+
return ReactCurrentDispatcher.current.useDeferredValue(value, initialValue);
592592
};
593593
exports.useEffect = function (create, deps) {
594594
return ReactCurrentDispatcher.current.useEffect(create, deps);
@@ -634,7 +634,7 @@ exports.useSyncExternalStore = function (
634634
exports.useTransition = function () {
635635
return ReactCurrentDispatcher.current.useTransition();
636636
};
637-
exports.version = "18.3.0-www-classic-fce6281b";
637+
exports.version = "18.3.0-www-classic-fcaf1567";
638638

639639
/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
640640
if (

compiled/facebook-www/React-profiling.modern.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -579,8 +579,8 @@ exports.useContext = function (Context) {
579579
return ReactCurrentDispatcher.current.useContext(Context);
580580
};
581581
exports.useDebugValue = function () {};
582-
exports.useDeferredValue = function (value) {
583-
return ReactCurrentDispatcher.current.useDeferredValue(value);
582+
exports.useDeferredValue = function (value, initialValue) {
583+
return ReactCurrentDispatcher.current.useDeferredValue(value, initialValue);
584584
};
585585
exports.useEffect = function (create, deps) {
586586
return ReactCurrentDispatcher.current.useEffect(create, deps);
@@ -626,7 +626,7 @@ exports.useSyncExternalStore = function (
626626
exports.useTransition = function () {
627627
return ReactCurrentDispatcher.current.useTransition();
628628
};
629-
exports.version = "18.3.0-www-modern-b51738eb";
629+
exports.version = "18.3.0-www-modern-316f00ed";
630630

631631
/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
632632
if (

compiled/facebook-www/ReactART-dev.classic.js

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ function _assertThisInitialized(self) {
6969
return self;
7070
}
7171

72-
var ReactVersion = "18.3.0-www-classic-01513ba4";
72+
var ReactVersion = "18.3.0-www-classic-839801a3";
7373

7474
var LegacyRoot = 0;
7575
var ConcurrentRoot = 1;
@@ -180,7 +180,9 @@ var replayFailedUnitOfWorkWithInvokeGuardedCallback =
180180
enableDO_NOT_USE_disableStrictPassiveEffect =
181181
dynamicFeatureFlags.enableDO_NOT_USE_disableStrictPassiveEffect,
182182
disableSchedulerTimeoutInWorkLoop =
183-
dynamicFeatureFlags.disableSchedulerTimeoutInWorkLoop; // On WWW, false is used for a new modern build.
183+
dynamicFeatureFlags.disableSchedulerTimeoutInWorkLoop,
184+
enableUseDeferredValueInitialArg =
185+
dynamicFeatureFlags.enableUseDeferredValueInitialArg; // On WWW, false is used for a new modern build.
184186
var enableProfilerTimer = true;
185187
var enableProfilerCommitHooks = true;
186188
var enableProfilerNestedUpdatePhase = true;
@@ -9740,34 +9742,61 @@ function updateMemo(nextCreate, deps) {
97409742
return nextValue;
97419743
}
97429744

9743-
function mountDeferredValue(value) {
9745+
function mountDeferredValue(value, initialValue) {
97449746
var hook = mountWorkInProgressHook();
9745-
hook.memoizedState = value;
9746-
return value;
9747+
return mountDeferredValueImpl(hook, value, initialValue);
97479748
}
97489749

9749-
function updateDeferredValue(value) {
9750+
function updateDeferredValue(value, initialValue) {
97509751
var hook = updateWorkInProgressHook();
97519752
var resolvedCurrentHook = currentHook;
97529753
var prevValue = resolvedCurrentHook.memoizedState;
97539754
return updateDeferredValueImpl(hook, prevValue, value);
97549755
}
97559756

9756-
function rerenderDeferredValue(value) {
9757+
function rerenderDeferredValue(value, initialValue) {
97579758
var hook = updateWorkInProgressHook();
97589759

97599760
if (currentHook === null) {
97609761
// This is a rerender during a mount.
9761-
hook.memoizedState = value;
9762-
return value;
9762+
return mountDeferredValueImpl(hook, value, initialValue);
97639763
} else {
97649764
// This is a rerender during an update.
97659765
var prevValue = currentHook.memoizedState;
97669766
return updateDeferredValueImpl(hook, prevValue, value);
97679767
}
97689768
}
97699769

9770-
function updateDeferredValueImpl(hook, prevValue, value) {
9770+
function mountDeferredValueImpl(hook, value, initialValue) {
9771+
if (enableUseDeferredValueInitialArg && initialValue !== undefined) {
9772+
// When `initialValue` is provided, we defer the initial render even if the
9773+
// current render is not synchronous.
9774+
// TODO: However, to avoid waterfalls, we should not defer if this render
9775+
// was itself spawned by an earlier useDeferredValue. Plan is to add a
9776+
// Deferred lane to track this.
9777+
hook.memoizedState = initialValue; // Schedule a deferred render
9778+
9779+
var deferredLane = claimNextTransitionLane();
9780+
currentlyRenderingFiber$1.lanes = mergeLanes(
9781+
currentlyRenderingFiber$1.lanes,
9782+
deferredLane
9783+
);
9784+
markSkippedUpdateLanes(deferredLane); // Set this to true to indicate that the rendered value is inconsistent
9785+
// from the latest value. The name "baseState" doesn't really match how we
9786+
// use it because we're reusing a state hook field instead of creating a
9787+
// new one.
9788+
9789+
hook.baseState = true;
9790+
return initialValue;
9791+
} else {
9792+
hook.memoizedState = value;
9793+
return value;
9794+
}
9795+
}
9796+
9797+
function updateDeferredValueImpl(hook, prevValue, value, initialValue) {
9798+
// TODO: We should also check if this component is going from
9799+
// hidden -> visible. If so, it should use the initialValue arg.
97719800
var shouldDeferValue = !includesOnlyNonUrgentLanes(renderLanes$1);
97729801

97739802
if (shouldDeferValue) {
@@ -10463,10 +10492,10 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
1046310492
mountHookTypesDev();
1046410493
return mountDebugValue();
1046510494
},
10466-
useDeferredValue: function (value) {
10495+
useDeferredValue: function (value, initialValue) {
1046710496
currentHookNameInDev = "useDeferredValue";
1046810497
mountHookTypesDev();
10469-
return mountDeferredValue(value);
10498+
return mountDeferredValue(value, initialValue);
1047010499
},
1047110500
useTransition: function () {
1047210501
currentHookNameInDev = "useTransition";
@@ -10602,10 +10631,10 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
1060210631
updateHookTypesDev();
1060310632
return mountDebugValue();
1060410633
},
10605-
useDeferredValue: function (value) {
10634+
useDeferredValue: function (value, initialValue) {
1060610635
currentHookNameInDev = "useDeferredValue";
1060710636
updateHookTypesDev();
10608-
return mountDeferredValue(value);
10637+
return mountDeferredValue(value, initialValue);
1060910638
},
1061010639
useTransition: function () {
1061110640
currentHookNameInDev = "useTransition";
@@ -10739,7 +10768,7 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
1073910768
updateHookTypesDev();
1074010769
return updateDebugValue();
1074110770
},
10742-
useDeferredValue: function (value) {
10771+
useDeferredValue: function (value, initialValue) {
1074310772
currentHookNameInDev = "useDeferredValue";
1074410773
updateHookTypesDev();
1074510774
return updateDeferredValue(value);
@@ -10878,10 +10907,10 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
1087810907
updateHookTypesDev();
1087910908
return updateDebugValue();
1088010909
},
10881-
useDeferredValue: function (value) {
10910+
useDeferredValue: function (value, initialValue) {
1088210911
currentHookNameInDev = "useDeferredValue";
1088310912
updateHookTypesDev();
10884-
return rerenderDeferredValue(value);
10913+
return rerenderDeferredValue(value, initialValue);
1088510914
},
1088610915
useTransition: function () {
1088710916
currentHookNameInDev = "useTransition";
@@ -11033,11 +11062,11 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
1103311062
mountHookTypesDev();
1103411063
return mountDebugValue();
1103511064
},
11036-
useDeferredValue: function (value) {
11065+
useDeferredValue: function (value, initialValue) {
1103711066
currentHookNameInDev = "useDeferredValue";
1103811067
warnInvalidHookAccess();
1103911068
mountHookTypesDev();
11040-
return mountDeferredValue(value);
11069+
return mountDeferredValue(value, initialValue);
1104111070
},
1104211071
useTransition: function () {
1104311072
currentHookNameInDev = "useTransition";
@@ -11194,7 +11223,7 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
1119411223
updateHookTypesDev();
1119511224
return updateDebugValue();
1119611225
},
11197-
useDeferredValue: function (value) {
11226+
useDeferredValue: function (value, initialValue) {
1119811227
currentHookNameInDev = "useDeferredValue";
1119911228
warnInvalidHookAccess();
1120011229
updateHookTypesDev();
@@ -11355,11 +11384,11 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null;
1135511384
updateHookTypesDev();
1135611385
return updateDebugValue();
1135711386
},
11358-
useDeferredValue: function (value) {
11387+
useDeferredValue: function (value, initialValue) {
1135911388
currentHookNameInDev = "useDeferredValue";
1136011389
warnInvalidHookAccess();
1136111390
updateHookTypesDev();
11362-
return rerenderDeferredValue(value);
11391+
return rerenderDeferredValue(value, initialValue);
1136311392
},
1136411393
useTransition: function () {
1136511394
currentHookNameInDev = "useTransition";

0 commit comments

Comments
 (0)