@@ -30,10 +30,10 @@ import {startPhaseTimer, stopPhaseTimer} from './ReactDebugFiberPerf';
3030import { StrictMode } from './ReactTypeOfMode' ;
3131import {
3232 enqueueUpdate ,
33- enqueueRenderPhaseUpdate ,
3433 processUpdateQueue ,
3534 createUpdate ,
3635} from './ReactUpdateQueue' ;
36+ import { NoWork } from './ReactFiberExpirationTime' ;
3737
3838const fakeInternalInstance = { } ;
3939const isArray = Array . isArray ;
@@ -109,32 +109,40 @@ if (__DEV__) {
109109 Object . freeze ( fakeInternalInstance ) ;
110110}
111111
112- export function createGetDerivedStateFromPropsUpdate (
112+ export function applyDerivedStateFromProps (
113+ workInProgress : Fiber ,
113114 getDerivedStateFromProps : ( props : any , state : any ) = > any ,
114- renderExpirationTime : ExpirationTime ,
115+ nextProps : any ,
115116) {
116- const update = createUpdate ( renderExpirationTime ) ;
117- update . process = ( nextWorkInProgress , prevState ) => {
118- const nextProps = nextWorkInProgress . pendingProps ;
117+ const prevState = workInProgress . memoizedState ;
119118
120- if (
121- debugRenderPhaseSideEffects ||
122- ( debugRenderPhaseSideEffectsForStrictMode &&
123- nextWorkInProgress . mode & StrictMode )
124- ) {
125- // Invoke the function an extra time to help detect side-effects.
126- getDerivedStateFromProps ( nextProps , prevState ) ;
127- }
119+ if (
120+ debugRenderPhaseSideEffects ||
121+ ( debugRenderPhaseSideEffectsForStrictMode &&
122+ workInProgress . mode & StrictMode )
123+ ) {
124+ // Invoke the function an extra time to help detect side-effects.
125+ getDerivedStateFromProps ( nextProps , prevState ) ;
126+ }
128127
129- const partialState = getDerivedStateFromProps ( nextProps , prevState ) ;
128+ const partialState = getDerivedStateFromProps ( nextProps , prevState ) ;
130129
131- if ( __DEV__ ) {
132- warnOnUndefinedDerivedState ( nextWorkInProgress , partialState ) ;
133- }
134- // Merge the partial state and the previous state.
135- return Object . assign ( { } , prevState , partialState ) ;
136- } ;
137- return update ;
130+ if ( __DEV__ ) {
131+ warnOnUndefinedDerivedState ( workInProgress , partialState ) ;
132+ }
133+ // Merge the partial state and the previous state.
134+ const memoizedState =
135+ partialState === null || partialState === undefined
136+ ? prevState
137+ : Object . assign ( { } , prevState , partialState ) ;
138+ workInProgress . memoizedState = memoizedState ;
139+
140+ // Once the update queue is empty, persist the derived state onto the
141+ // base state.
142+ const updateQueue = workInProgress . updateQueue ;
143+ if ( updateQueue !== null && updateQueue . expirationTime === NoWork ) {
144+ updateQueue . baseState = memoizedState ;
145+ }
138146}
139147
140148export default function (
@@ -742,19 +750,20 @@ export default function(
742750 }
743751 }
744752
753+ let updateQueue = workInProgress . updateQueue ;
754+ if ( updateQueue !== null ) {
755+ processUpdateQueue ( workInProgress , updateQueue , renderExpirationTime ) ;
756+ instance . state = workInProgress . memoizedState ;
757+ }
758+
745759 const getDerivedStateFromProps =
746760 workInProgress . type . getDerivedStateFromProps ;
747761 if ( typeof getDerivedStateFromProps === 'function' ) {
748- const update = createGetDerivedStateFromPropsUpdate (
762+ applyDerivedStateFromProps (
763+ workInProgress ,
749764 getDerivedStateFromProps ,
750- renderExpirationTime ,
765+ props ,
751766 ) ;
752- enqueueRenderPhaseUpdate ( workInProgress , update , renderExpirationTime ) ;
753- }
754-
755- let updateQueue = workInProgress . updateQueue ;
756- if ( updateQueue !== null ) {
757- processUpdateQueue ( workInProgress , updateQueue , renderExpirationTime ) ;
758767 instance . state = workInProgress . memoizedState ;
759768 }
760769
@@ -796,8 +805,9 @@ export default function(
796805 const newUnmaskedContext = getUnmaskedContext ( workInProgress ) ;
797806 const newContext = getMaskedContext ( workInProgress , newUnmaskedContext ) ;
798807
808+ const getDerivedStateFromProps = ctor . getDerivedStateFromProps ;
799809 const hasNewLifecycles =
800- typeof ctor . getDerivedStateFromProps === 'function' ||
810+ typeof getDerivedStateFromProps === 'function' ||
801811 typeof instance . getSnapshotBeforeUpdate === 'function' ;
802812
803813 // Note: During these life-cycles, instance.props/instance.state are what
@@ -821,19 +831,6 @@ export default function(
821831 }
822832 }
823833
824- // Only call getDerivedStateFromProps if the props have changed
825- if ( oldProps !== newProps ) {
826- const getDerivedStateFromProps =
827- workInProgress . type . getDerivedStateFromProps ;
828- if ( typeof getDerivedStateFromProps === 'function' ) {
829- const update = createGetDerivedStateFromPropsUpdate (
830- getDerivedStateFromProps ,
831- renderExpirationTime ,
832- ) ;
833- enqueueRenderPhaseUpdate ( workInProgress , update , renderExpirationTime ) ;
834- }
835- }
836-
837834 const oldState = workInProgress . memoizedState ;
838835 let newState = ( instance . state = oldState ) ;
839836 let updateQueue = workInProgress . updateQueue ;
@@ -842,6 +839,15 @@ export default function(
842839 newState = workInProgress . memoizedState ;
843840 }
844841
842+ if ( typeof getDerivedStateFromProps === 'function' ) {
843+ applyDerivedStateFromProps (
844+ workInProgress ,
845+ getDerivedStateFromProps ,
846+ newProps ,
847+ ) ;
848+ newState = workInProgress . memoizedState ;
849+ }
850+
845851 if (
846852 oldProps === newProps &&
847853 oldState === newState &&
@@ -927,8 +933,9 @@ export default function(
927933 const newUnmaskedContext = getUnmaskedContext ( workInProgress ) ;
928934 const newContext = getMaskedContext ( workInProgress , newUnmaskedContext ) ;
929935
936+ const getDerivedStateFromProps = ctor . getDerivedStateFromProps ;
930937 const hasNewLifecycles =
931- typeof ctor . getDerivedStateFromProps === 'function' ||
938+ typeof getDerivedStateFromProps === 'function' ||
932939 typeof instance . getSnapshotBeforeUpdate === 'function' ;
933940
934941 // Note: During these life-cycles, instance.props/instance.state are what
@@ -952,19 +959,6 @@ export default function(
952959 }
953960 }
954961
955- // Only call getDerivedStateFromProps if the props have changed
956- if ( oldProps !== newProps ) {
957- const getDerivedStateFromProps =
958- workInProgress . type . getDerivedStateFromProps ;
959- if ( typeof getDerivedStateFromProps === 'function' ) {
960- const update = createGetDerivedStateFromPropsUpdate (
961- getDerivedStateFromProps ,
962- renderExpirationTime ,
963- ) ;
964- enqueueRenderPhaseUpdate ( workInProgress , update , renderExpirationTime ) ;
965- }
966- }
967-
968962 const oldState = workInProgress . memoizedState ;
969963 let newState = ( instance . state = oldState ) ;
970964 let updateQueue = workInProgress . updateQueue ;
@@ -973,6 +967,15 @@ export default function(
973967 newState = workInProgress . memoizedState ;
974968 }
975969
970+ if ( typeof getDerivedStateFromProps === 'function' ) {
971+ applyDerivedStateFromProps (
972+ workInProgress ,
973+ getDerivedStateFromProps ,
974+ newProps ,
975+ ) ;
976+ newState = workInProgress . memoizedState ;
977+ }
978+
976979 if (
977980 oldProps === newProps &&
978981 oldState === newState &&
0 commit comments