27
import type {Lanes, Lane} from './ReactFiberLane';
28
import type {HookFlags} from './ReactHookEffectTags';
29
import type {Flags} from './ReactFiberFlags';
30
+import type {TransitionStatus} from './ReactFiberConfig';
31
32
+import {NotPendingTransition as NoPendingHostTransition} from './ReactFiberConfig';
33
import ReactSharedInternals from 'shared/ReactSharedInternals';
34
import {
35
enableDebugTracing,
148
import type {ThenableState} from './ReactFiberThenable';
149
import type {BatchConfigTransition} from './ReactFiberTracingMarkerComponent';
150
import {requestAsyncActionContext} from './ReactFiberAsyncAction';
151
+import {HostTransitionContext} from './ReactFiberHostContext';
152
153
const {ReactCurrentDispatcher, ReactCurrentBatchConfig} = ReactSharedInternals;
154
760
current: Fiber | null,
761
workInProgress: Fiber,
762
lanes: Lanes,
760
-): boolean {
763
+): TransitionStatus {
764
if (!(enableFormActions && enableAsyncActions)) {
762
- return false;
765
+ throw new Error('Not implemented.');
766
}
767
return renderWithHooks(
768
current,
774
);
775
}
776
774
-export function TransitionAwareHostComponent(): boolean {
777
+export function TransitionAwareHostComponent(): TransitionStatus {
778
if (!(enableFormActions && enableAsyncActions)) {
776
- return false;
779
+ throw new Error('Not implemented.');
780
}
781
const dispatcher = ReactCurrentDispatcher.current;
779
- const [isPending] = dispatcher.useTransition();
780
- return isPending;
782
+ const [maybeThenable] = dispatcher.useState();
783
+ if (typeof maybeThenable.then === 'function') {
784
+ const thenable: Thenable<TransitionStatus> = (maybeThenable: any);
785
+ return useThenable(thenable);
786
+ } else {
787
+ const status: TransitionStatus = maybeThenable;
788
+ return status;
789
+ }
790
}
791
792
export function checkDidRenderIdHook(): boolean {
2526
2527
export function startHostTransition<F>(
2528
formFiber: Fiber,
2529
+ pendingState: TransitionStatus,
2530
callback: F => mixed,
2531
formData: F,
2532
): void {
2555
// it was stateful all along so we can reuse most of the implementation
2556
// for function components and useTransition.
2557
//
2548
- // Create the initial hooks used by useTransition. This is essentially an
2549
- // inlined version of mountTransition.
2558
+ // Create the state hook used by TransitionAwareHostComponent. This is
2559
+ // essentially an inlined version of mountState.
2560
const queue: UpdateQueue<
2551
- Thenable<boolean> | boolean,
2552
- Thenable<boolean> | boolean,
2561
+ Thenable<TransitionStatus> | TransitionStatus,
2562
+ Thenable<TransitionStatus> | TransitionStatus,
2563
> = {
2564
pending: null,
2565
lanes: NoLanes,
2566
dispatch: null,
2567
lastRenderedReducer: basicStateReducer,
2558
- lastRenderedState: false,
2568
+ lastRenderedState: NoPendingHostTransition,
2569
};
2570
const stateHook: Hook = {
2561
- memoizedState: false,
2562
- baseState: false,
2571
+ memoizedState: NoPendingHostTransition,
2572
+ baseState: NoPendingHostTransition,
2573
baseQueue: null,
2574
queue: queue,
2575
next: null,
2576
};
2577
2568
- const dispatch: (Thenable<boolean> | boolean) => void =
2578
+ const dispatch: (Thenable<TransitionStatus> | TransitionStatus) => void =
2579
(dispatchSetState.bind(null, formFiber, queue): any);
2580
setPending = queue.dispatch = dispatch;
2581
2572
- // TODO: The only reason this second hook exists is to save a reference to
2573
- // the `dispatch` function. But we already store this on the state hook. So
2574
- // we can cheat and read it from there. Need to make this change to the
2575
- // regular `useTransition` implementation, too.
2576
- const transitionHook: Hook = {
2577
- memoizedState: dispatch,
2578
- baseState: null,
2579
- baseQueue: null,
2580
- queue: null,
2581
- next: null,
2582
- };
2583
-
2584
- stateHook.next = transitionHook;
2585
-
2586
- // Add the initial list of hooks to both fiber alternates. The idea is that
2587
- // the fiber had these hooks all along.
2582
+ // Add the state hook to both fiber alternates. The idea is that the fiber
2583
+ // had this hook all along.
2584
formFiber.memoizedState = stateHook;
2585
const alternate = formFiber.alternate;
2586
if (alternate !== null) {
2588
}
2589
} else {
2590
// This fiber was already upgraded to be stateful.
2595
- const transitionHook: Hook = formFiber.memoizedState.next;
2596
- const dispatch: (Thenable<boolean> | boolean) => void =
2597
- transitionHook.memoizedState;
2591
+ const stateHook: Hook = formFiber.memoizedState;
2592
+ const dispatch: (Thenable<TransitionStatus> | TransitionStatus) => void =
2593
+ stateHook.queue.dispatch;
2594
setPending = dispatch;
2595
}
2596
2597
startTransition(
2602
- true,
2603
- false,
2598
+ pendingState,
2599
+ NoPendingHostTransition,
2600
setPending,
2601
// TODO: We can avoid this extra wrapper, somehow. Figure out layering
2602
// once more of this function is implemented.
2646
return [isPending, start];
2647
}
2648
2649
+function useHostTransitionStatus(): TransitionStatus {
2650
+ if (!(enableFormActions && enableAsyncActions)) {
2651
+ throw new Error('Not implemented.');
2652
+ }
2653
+ const status: TransitionStatus | null = readContext(HostTransitionContext);
2654
+ return status !== null ? status : NoPendingHostTransition;
2655
+}
2656
+
2657
function mountId(): string {
2658
const hook = mountWorkInProgressHook();
2659
2981
if (enableUseEffectEventHook) {
2982
(ContextOnlyDispatcher: Dispatcher).useEffectEvent = throwInvalidHookError;
2983
}
2984
+if (enableFormActions && enableAsyncActions) {
2985
+ (ContextOnlyDispatcher: Dispatcher).useHostTransitionStatus =
2986
+ throwInvalidHookError;
2987
+}
2988
2989
const HooksDispatcherOnMount: Dispatcher = {
2990
readContext,
3016
if (enableUseEffectEventHook) {
3017
(HooksDispatcherOnMount: Dispatcher).useEffectEvent = mountEvent;
3018
}
3019
+if (enableFormActions && enableAsyncActions) {
3020
+ (HooksDispatcherOnMount: Dispatcher).useHostTransitionStatus =
3021
+ useHostTransitionStatus;
3022
+}
3023
const HooksDispatcherOnUpdate: Dispatcher = {
3024
readContext,
3025
3050
if (enableUseEffectEventHook) {
3051
(HooksDispatcherOnUpdate: Dispatcher).useEffectEvent = updateEvent;
3052
}
3053
+if (enableFormActions && enableAsyncActions) {
3054
+ (HooksDispatcherOnUpdate: Dispatcher).useHostTransitionStatus =
3055
+ useHostTransitionStatus;
3056
+}
3057
3058
const HooksDispatcherOnRerender: Dispatcher = {
3059
readContext,
3085
if (enableUseEffectEventHook) {
3086
(HooksDispatcherOnRerender: Dispatcher).useEffectEvent = updateEvent;
3087
}
3088
+if (enableFormActions && enableAsyncActions) {
3089
+ (HooksDispatcherOnRerender: Dispatcher).useHostTransitionStatus =
3090
+ useHostTransitionStatus;
3091
+}
3092
3093
let HooksDispatcherOnMountInDEV: Dispatcher | null = null;
3094
let HooksDispatcherOnMountWithHookTypesInDEV: Dispatcher | null = null;
3275
return mountEvent(callback);
3276
};
3277
}
3278
+ if (enableFormActions && enableAsyncActions) {
3279
+ (HooksDispatcherOnMountInDEV: Dispatcher).useHostTransitionStatus =
3280
+ useHostTransitionStatus;
3281
+ }
3282
3283
HooksDispatcherOnMountWithHookTypesInDEV = {
3284
readContext<T>(context: ReactContext<T>): T {
3433
return mountEvent(callback);
3434
};
3435
}
3436
+ if (enableFormActions && enableAsyncActions) {
3437
+ (HooksDispatcherOnMountWithHookTypesInDEV: Dispatcher).useHostTransitionStatus =
3438
+ useHostTransitionStatus;
3439
+ }
3440
3441
HooksDispatcherOnUpdateInDEV = {
3442
readContext<T>(context: ReactContext<T>): T {
3593
return updateEvent(callback);
3594
};
3595
}
3596
+ if (enableFormActions && enableAsyncActions) {
3597
+ (HooksDispatcherOnUpdateInDEV: Dispatcher).useHostTransitionStatus =
3598
+ useHostTransitionStatus;
3599
+ }
3600
3601
HooksDispatcherOnRerenderInDEV = {
3602
readContext<T>(context: ReactContext<T>): T {
3753
return updateEvent(callback);
3754
};
3755
}
3756
+ if (enableFormActions && enableAsyncActions) {
3757
+ (HooksDispatcherOnRerenderInDEV: Dispatcher).useHostTransitionStatus =
3758
+ useHostTransitionStatus;
3759
+ }
3760
3761
InvalidNestedHooksDispatcherOnMountInDEV = {
3762
readContext<T>(context: ReactContext<T>): T {
3935
return mountEvent(callback);
3936
};
3937
}
3938
+ if (enableFormActions && enableAsyncActions) {
3939
+ (InvalidNestedHooksDispatcherOnMountInDEV: Dispatcher).useHostTransitionStatus =
3940
+ useHostTransitionStatus;
3941
+ }
3942
3943
InvalidNestedHooksDispatcherOnUpdateInDEV = {
3944
readContext<T>(context: ReactContext<T>): T {
4120
return updateEvent(callback);
4121
};
4122
}
4123
+ if (enableFormActions && enableAsyncActions) {
4124
+ (InvalidNestedHooksDispatcherOnUpdateInDEV: Dispatcher).useHostTransitionStatus =
4125
+ useHostTransitionStatus;
4126
+ }
4127
4128
InvalidNestedHooksDispatcherOnRerenderInDEV = {
4129
readContext<T>(context: ReactContext<T>): T {
4305
return updateEvent(callback);
4306
};
4307
}
4308
+ if (enableFormActions && enableAsyncActions) {
4309
+ (InvalidNestedHooksDispatcherOnRerenderInDEV: Dispatcher).useHostTransitionStatus =
4310
+ useHostTransitionStatus;
4311
+ }
4312
}