@@ -13,6 +13,7 @@ import type {
13
13
Usable ,
14
14
Thenable ,
15
15
RejectedThenable ,
16
+ Awaited ,
16
17
} from 'shared/ReactTypes' ;
17
18
import type {
18
19
Fiber ,
@@ -1871,12 +1872,12 @@ function rerenderOptimistic<S, A>(
1871
1872
type FormStateActionQueue < S , P > = {
1872
1873
// This is the most recent state returned from an action. It's updated as
1873
1874
// soon as the action finishes running.
1874
- state : S ,
1875
+ state : Awaited < S > ,
1875
1876
// A stable dispatch method, passed to the user.
1876
1877
dispatch : Dispatch < P > ,
1877
1878
// This is the most recent action function that was rendered. It's updated
1878
1879
// during the commit phase.
1879
- action : ( S , P ) => Promise < S > ,
1880
+ action : ( Awaited < S > , P ) => S ,
1880
1881
// This is a circular linked list of pending action payloads. It incudes the
1881
1882
// action that is currently running.
1882
1883
pending : FormStateActionQueueNode < P > | null ,
@@ -1891,7 +1892,7 @@ type FormStateActionQueueNode<P> = {
1891
1892
function dispatchFormState < S , P > (
1892
1893
fiber : Fiber ,
1893
1894
actionQueue : FormStateActionQueue < S , P > ,
1894
- setState : Dispatch < S | Thenable < S >> ,
1895
+ setState : Dispatch < S | Awaited < S >> ,
1895
1896
payload : P ,
1896
1897
) : void {
1897
1898
if ( isRenderPhaseUpdate ( fiber ) ) {
@@ -1907,7 +1908,7 @@ function dispatchFormState<S, P>(
1907
1908
} ;
1908
1909
newLast . next = actionQueue . pending = newLast ;
1909
1910
1910
- runFormStateAction ( actionQueue , setState , payload ) ;
1911
+ runFormStateAction ( actionQueue , ( setState : any ) , payload ) ;
1911
1912
} else {
1912
1913
// There's already an action running. Add to the queue.
1913
1914
const first = last . next ;
@@ -1921,7 +1922,7 @@ function dispatchFormState<S, P>(
1921
1922
1922
1923
function runFormStateAction < S , P > (
1923
1924
actionQueue : FormStateActionQueue < S , P > ,
1924
- setState : Dispatch < S | Thenable < S >> ,
1925
+ setState : Dispatch < S | Awaited < S >> ,
1925
1926
payload : P ,
1926
1927
) {
1927
1928
const action = actionQueue . action ;
@@ -1942,42 +1943,42 @@ function runFormStateAction<S, P>(
1942
1943
// $FlowFixMe[method-unbinding]
1943
1944
typeof returnValue . then === 'function'
1944
1945
) {
1945
- const thenable = ( ( returnValue : any ) : Thenable < S > ) ;
1946
+ const thenable = ( ( returnValue : any ) : Thenable < Awaited < S > >) ;
1946
1947
1947
- // Attach a listener to read the return state of the action. As soon as this
1948
- // resolves, we can run the next action in the sequence.
1948
+ // Attach a listener to read the return state of the action. As soon as
1949
+ // this resolves, we can run the next action in the sequence.
1949
1950
thenable . then (
1950
- ( nextState : S ) => {
1951
+ ( nextState : Awaited < S > ) => {
1951
1952
actionQueue . state = nextState ;
1952
- finishRunningFormStateAction ( actionQueue , setState ) ;
1953
+ finishRunningFormStateAction ( actionQueue , ( setState : any ) ) ;
1953
1954
} ,
1954
- ( ) => finishRunningFormStateAction ( actionQueue , setState ) ,
1955
+ ( ) => finishRunningFormStateAction ( actionQueue , ( setState : any ) ) ,
1955
1956
) ;
1956
1957
1957
1958
const entangledResult = requestAsyncActionContext < S > ( thenable , null ) ;
1958
- setState ( entangledResult ) ;
1959
+ setState ( ( entangledResult : any ) ) ;
1959
1960
} else {
1960
- // This is either `finishedState` or a thenable that resolves to
1961
- // `finishedState`, depending on whether we're inside an async
1962
- // action scope.
1961
+ // This is either `returnValue` or a thenable that resolves to
1962
+ // `returnValue`, depending on whether we're inside an async action scope.
1963
1963
const entangledResult = requestSyncActionContext < S > ( returnValue , null ) ;
1964
- setState ( entangledResult ) ;
1964
+ setState ( ( entangledResult : any ) ) ;
1965
1965
1966
- const nextState = ( ( returnValue : any ) : S ) ;
1966
+ const nextState = ( ( returnValue : any ) : Awaited < S > ) ;
1967
1967
actionQueue . state = nextState ;
1968
- finishRunningFormStateAction ( actionQueue , setState ) ;
1968
+ finishRunningFormStateAction ( actionQueue , ( setState : any ) ) ;
1969
1969
}
1970
1970
} catch ( error ) {
1971
1971
// This is a trick to get the `useFormState` hook to rethrow the error.
1972
1972
// When it unwraps the thenable with the `use` algorithm, the error
1973
1973
// will be thrown.
1974
- const rejectedThenable : RejectedThenable < S > = {
1974
+ const rejectedThenable : S = ( {
1975
1975
then ( ) { } ,
1976
1976
status : 'rejected' ,
1977
1977
reason : error ,
1978
- } ;
1978
+ // $FlowFixMe: Not sure why this doesn't work
1979
+ } : RejectedThenable < Awaited < S >> ) ;
1979
1980
setState ( rejectedThenable ) ;
1980
- finishRunningFormStateAction ( actionQueue , setState ) ;
1981
+ finishRunningFormStateAction ( actionQueue , ( setState : any ) ) ;
1981
1982
} finally {
1982
1983
ReactCurrentBatchConfig . transition = prevTransition ;
1983
1984
@@ -1999,7 +2000,7 @@ function runFormStateAction<S, P>(
1999
2000
2000
2001
function finishRunningFormStateAction < S , P > (
2001
2002
actionQueue : FormStateActionQueue < S , P > ,
2002
- setState : Dispatch < S | Thenable < S >> ,
2003
+ setState : Dispatch < S | Awaited < S >> ,
2003
2004
) {
2004
2005
// The action finished running. Pop it from the queue and run the next pending
2005
2006
// action, if there are any.
@@ -2015,7 +2016,7 @@ function finishRunningFormStateAction<S, P>(
2015
2016
last . next = next ;
2016
2017
2017
2018
// Run the next action.
2018
- runFormStateAction ( actionQueue , setState , next . payload ) ;
2019
+ runFormStateAction ( actionQueue , ( setState : any ) , next . payload ) ;
2019
2020
}
2020
2021
}
2021
2022
}
@@ -2025,11 +2026,11 @@ function formStateReducer<S>(oldState: S, newState: S): S {
2025
2026
}
2026
2027
2027
2028
function mountFormState< S , P > (
2028
- action: (S , P) => Promise < S > ,
2029
- initialStateProp: S ,
2029
+ action: (Awaited < S > , P) => S ,
2030
+ initialStateProp : Awaited < S > ,
2030
2031
permalink?: string,
2031
- ): [S , (P) => void ] {
2032
- let initialState = initialStateProp ;
2032
+ ): [Awaited < S > , (P) => void ] {
2033
+ let initialState : Awaited < S > = initialStateProp ;
2033
2034
if ( getIsHydrating ( ) ) {
2034
2035
const root : FiberRoot = ( getWorkInProgressRoot ( ) : any ) ;
2035
2036
const ssrFormState = root . formState ;
@@ -2050,18 +2051,20 @@ function mountFormState<S, P>(
2050
2051
// the `use` algorithm during render.
2051
2052
const stateHook = mountWorkInProgressHook ( ) ;
2052
2053
stateHook . memoizedState = stateHook . baseState = initialState ;
2053
- const stateQueue : UpdateQueue < S | Thenable < S > , S | Thenable < S >> = {
2054
+ // TODO: Typing this "correctly" results in recursion limit errors
2055
+ // const stateQueue: UpdateQueue<S | Awaited<S>, S | Awaited<S>> = {
2056
+ const stateQueue = {
2054
2057
pending : null ,
2055
2058
lanes : NoLanes ,
2056
- dispatch : null ,
2059
+ dispatch : ( null : any ) ,
2057
2060
lastRenderedReducer : formStateReducer ,
2058
2061
lastRenderedState : initialState ,
2059
2062
} ;
2060
2063
stateHook . queue = stateQueue ;
2061
- const setState : Dispatch < S | Thenable < S >> = ( dispatchSetState . bind (
2064
+ const setState : Dispatch < S | Awaited < S >> = ( dispatchSetState . bind (
2062
2065
null ,
2063
2066
currentlyRenderingFiber ,
2064
- stateQueue ,
2067
+ ( ( stateQueue : any ) : UpdateQueue < S | Awaited < S > , S | Awaited < S >> ) ,
2065
2068
) : any ) ;
2066
2069
stateQueue . dispatch = setState ;
2067
2070
@@ -2077,7 +2080,7 @@ function mountFormState<S, P>(
2077
2080
pending : null ,
2078
2081
} ;
2079
2082
actionQueueHook . queue = actionQueue ;
2080
- const dispatch = dispatchFormState . bind (
2083
+ const dispatch = ( dispatchFormState : any ) . bind (
2081
2084
null ,
2082
2085
currentlyRenderingFiber ,
2083
2086
actionQueue ,
@@ -2094,10 +2097,10 @@ function mountFormState<S, P>(
2094
2097
}
2095
2098
2096
2099
function updateFormState < S , P > (
2097
- action : ( S , P ) => Promise < S > ,
2098
- initialState : S ,
2100
+ action : ( Awaited < S > , P ) => S ,
2101
+ initialState : Awaited < S > ,
2099
2102
permalink ?: string ,
2100
- ) : [ S , ( P ) => void ] {
2103
+ ) : [ Awaited < S > , ( P ) => void ] {
2101
2104
const stateHook = updateWorkInProgressHook ( ) ;
2102
2105
const currentStateHook = ( ( currentHook : any ) : Hook ) ;
2103
2106
return updateFormStateImpl (
@@ -2112,23 +2115,23 @@ function updateFormState<S, P>(
2112
2115
function updateFormStateImpl < S , P > (
2113
2116
stateHook : Hook ,
2114
2117
currentStateHook : Hook ,
2115
- action : ( S , P ) => Promise < S > ,
2116
- initialState : S ,
2118
+ action : ( Awaited < S > , P ) => S ,
2119
+ initialState : Awaited < S > ,
2117
2120
permalink ? : string ,
2118
- ) : [ S , ( P ) => void ] {
2121
+ ) : [ Awaited < S > , ( P ) => void ] {
2119
2122
const [ actionResult ] = updateReducerImpl < S | Thenable < S > , S | Thenable < S >> (
2120
2123
stateHook ,
2121
2124
currentStateHook ,
2122
2125
formStateReducer ,
2123
2126
) ;
2124
2127
2125
2128
// This will suspend until the action finishes.
2126
- const state : S =
2129
+ const state : Awaited < S > =
2127
2130
typeof actionResult === 'object' &&
2128
2131
actionResult !== null &&
2129
2132
// $FlowFixMe[method-unbinding]
2130
2133
typeof actionResult . then === 'function'
2131
- ? useThenable ( ( ( actionResult : any ) : Thenable < S > ) )
2134
+ ? useThenable ( ( ( actionResult : any ) : Thenable < Awaited < S > >) )
2132
2135
: ( actionResult : any ) ;
2133
2136
2134
2137
const actionQueueHook = updateWorkInProgressHook ( ) ;
@@ -2152,16 +2155,16 @@ function updateFormStateImpl<S, P>(
2152
2155
2153
2156
function formStateActionEffect < S , P > (
2154
2157
actionQueue : FormStateActionQueue < S , P > ,
2155
- action : ( S , P ) => Promise < S > ,
2158
+ action : ( Awaited < S > , P ) => S ,
2156
2159
) : void {
2157
2160
actionQueue . action = action ;
2158
2161
}
2159
2162
2160
2163
function rerenderFormState < S , P > (
2161
- action : ( S , P ) = > Promise < S > ,
2162
- initialState : S ,
2164
+ action : ( Awaited < S > , P ) = > S ,
2165
+ initialState : Awaited < S > ,
2163
2166
permalink?: string,
2164
- ) : [ S , ( P ) => void ] {
2167
+ ): [Awaited < S > , (P) => void ] {
2165
2168
// Unlike useState, useFormState doesn't support render phase updates.
2166
2169
// Also unlike useState, we need to replay all pending updates again in case
2167
2170
// the passthrough value changed.
@@ -2184,7 +2187,7 @@ function rerenderFormState<S, P>(
2184
2187
}
2185
2188
2186
2189
// This is a mount. No updates to process.
2187
- const state : S = stateHook . memoizedState ;
2190
+ const state : Awaited < S > = stateHook . memoizedState ;
2188
2191
2189
2192
const actionQueueHook = updateWorkInProgressHook ( ) ;
2190
2193
const actionQueue = actionQueueHook . queue ;
@@ -3735,10 +3738,10 @@ if (__DEV__) {
3735
3738
useHostTransitionStatus ;
3736
3739
( HooksDispatcherOnMountInDEV : Dispatcher ) . useFormState =
3737
3740
function useFormState < S , P > (
3738
- action : ( S , P ) = > Promise < S > ,
3739
- initialState : S ,
3741
+ action : ( Awaited < S > , P ) = > S ,
3742
+ initialState : Awaited < S > ,
3740
3743
permalink ?: string ,
3741
- ) : [ S , ( P ) => void ] {
3744
+ ) : [ Awaited < S > , ( P ) => void ] {
3742
3745
currentHookNameInDev = 'useFormState' ;
3743
3746
mountHookTypesDev ( ) ;
3744
3747
return mountFormState ( action , initialState , permalink ) ;
@@ -3905,10 +3908,10 @@ if (__DEV__) {
3905
3908
useHostTransitionStatus ;
3906
3909
( HooksDispatcherOnMountWithHookTypesInDEV : Dispatcher ) . useFormState =
3907
3910
function useFormState < S , P > (
3908
- action : ( S , P ) = > Promise < S > ,
3909
- initialState : S ,
3911
+ action : ( Awaited < S > , P ) = > S ,
3912
+ initialState : Awaited < S > ,
3910
3913
permalink ?: string ,
3911
- ) : [ S , ( P ) => void ] {
3914
+ ) : [ Awaited < S > , ( P ) => void ] {
3912
3915
currentHookNameInDev = 'useFormState' ;
3913
3916
updateHookTypesDev ( ) ;
3914
3917
return mountFormState ( action , initialState , permalink ) ;
@@ -4077,10 +4080,10 @@ if (__DEV__) {
4077
4080
useHostTransitionStatus ;
4078
4081
( HooksDispatcherOnUpdateInDEV : Dispatcher ) . useFormState =
4079
4082
function useFormState < S , P > (
4080
- action : ( S , P ) = > Promise < S > ,
4081
- initialState : S ,
4083
+ action : ( Awaited < S > , P ) = > S ,
4084
+ initialState : Awaited < S > ,
4082
4085
permalink ?: string ,
4083
- ) : [ S , ( P ) => void ] {
4086
+ ) : [ Awaited < S > , ( P ) => void ] {
4084
4087
currentHookNameInDev = 'useFormState' ;
4085
4088
updateHookTypesDev ( ) ;
4086
4089
return updateFormState ( action , initialState , permalink ) ;
@@ -4249,10 +4252,10 @@ if (__DEV__) {
4249
4252
useHostTransitionStatus ;
4250
4253
( HooksDispatcherOnRerenderInDEV : Dispatcher ) . useFormState =
4251
4254
function useFormState < S , P > (
4252
- action : ( S , P ) = > Promise < S > ,
4253
- initialState : S ,
4255
+ action : ( Awaited < S > , P ) = > S ,
4256
+ initialState : Awaited < S > ,
4254
4257
permalink ?: string ,
4255
- ) : [ S , ( P ) => void ] {
4258
+ ) : [ Awaited < S > , ( P ) => void ] {
4256
4259
currentHookNameInDev = 'useFormState' ;
4257
4260
updateHookTypesDev ( ) ;
4258
4261
return rerenderFormState ( action , initialState , permalink ) ;
@@ -4442,10 +4445,10 @@ if (__DEV__) {
4442
4445
useHostTransitionStatus ;
4443
4446
( InvalidNestedHooksDispatcherOnMountInDEV : Dispatcher ) . useFormState =
4444
4447
function useFormState < S , P > (
4445
- action : ( S , P ) = > Promise < S > ,
4446
- initialState : S ,
4448
+ action : ( Awaited < S > , P ) = > S ,
4449
+ initialState : Awaited < S > ,
4447
4450
permalink ?: string ,
4448
- ) : [ S , ( P ) => void ] {
4451
+ ) : [ Awaited < S > , ( P ) => void ] {
4449
4452
currentHookNameInDev = 'useFormState' ;
4450
4453
warnInvalidHookAccess ( ) ;
4451
4454
mountHookTypesDev ( ) ;
@@ -4640,10 +4643,10 @@ if (__DEV__) {
4640
4643
useHostTransitionStatus ;
4641
4644
( InvalidNestedHooksDispatcherOnUpdateInDEV : Dispatcher ) . useFormState =
4642
4645
function useFormState < S , P > (
4643
- action : ( S , P ) = > Promise < S > ,
4644
- initialState : S ,
4646
+ action : ( Awaited < S > , P ) = > S ,
4647
+ initialState : Awaited < S > ,
4645
4648
permalink ?: string ,
4646
- ) : [ S , ( P ) => void ] {
4649
+ ) : [ Awaited < S > , ( P ) => void ] {
4647
4650
currentHookNameInDev = 'useFormState' ;
4648
4651
warnInvalidHookAccess ( ) ;
4649
4652
updateHookTypesDev ( ) ;
@@ -4838,10 +4841,10 @@ if (__DEV__) {
4838
4841
useHostTransitionStatus ;
4839
4842
( InvalidNestedHooksDispatcherOnRerenderInDEV : Dispatcher ) . useFormState =
4840
4843
function useFormState < S , P > (
4841
- action : ( S , P ) = > Promise < S > ,
4842
- initialState : S ,
4844
+ action : ( Awaited < S > , P ) = > S ,
4845
+ initialState : Awaited < S > ,
4843
4846
permalink ?: string ,
4844
- ) : [ S , ( P ) => void ] {
4847
+ ) : [ Awaited < S > , ( P ) => void ] {
4845
4848
currentHookNameInDev = 'useFormState' ;
4846
4849
warnInvalidHookAccess ( ) ;
4847
4850
updateHookTypesDev ( ) ;
0 commit comments