23
enableDebugTracing,
24
enableSchedulingProfiler,
25
enableLazyContextPropagation,
26
+ enableRefAsProp,
27
} from 'shared/ReactFeatureFlags';
28
import ReactStrictModeWarnings from './ReactStrictModeWarnings';
29
import {isMounted} from './ReactFiberTreeReflection';
35
import isArray from 'shared/isArray';
36
import {REACT_CONTEXT_TYPE, REACT_CONSUMER_TYPE} from 'shared/ReactSymbols';
37
37
-import {resolveDefaultProps} from './ReactFiberLazyComponent';
38
import {
39
DebugTracingMode,
40
NoMode,
904
): boolean {
905
const instance = workInProgress.stateNode;
906
907
- const oldProps = workInProgress.memoizedProps;
907
+ const unresolvedOldProps = workInProgress.memoizedProps;
908
+ const oldProps = resolveClassComponentProps(
909
+ ctor,
910
+ unresolvedOldProps,
911
+ workInProgress.type === workInProgress.elementType,
912
+ );
913
instance.props = oldProps;
914
915
const oldContext = instance.context;
931
typeof getDerivedStateFromProps === 'function' ||
932
typeof instance.getSnapshotBeforeUpdate === 'function';
933
934
+ // When comparing whether props changed, we should compare using the
935
+ // unresolved props object that is stored on the fiber, rather than the
936
+ // one that gets assigned to the instance, because that object may have been
937
+ // cloned to resolve default props and/or remove `ref`.
938
+ const unresolvedNewProps = workInProgress.pendingProps;
939
+ const didReceiveNewProps = unresolvedNewProps !== unresolvedOldProps;
940
+
941
// Note: During these life-cycles, instance.props/instance.state are what
942
// ever the previously attempted to render - not the "current". However,
943
// during componentDidUpdate we pass the "current" props.
949
(typeof instance.UNSAFE_componentWillReceiveProps === 'function' ||
950
typeof instance.componentWillReceiveProps === 'function')
951
) {
940
- if (oldProps !== newProps || oldContext !== nextContext) {
952
+ if (didReceiveNewProps || oldContext !== nextContext) {
953
callComponentWillReceiveProps(
954
workInProgress,
955
instance,
967
suspendIfUpdateReadFromEntangledAsyncAction();
968
newState = workInProgress.memoizedState;
969
if (
958
- oldProps === newProps &&
970
+ !didReceiveNewProps &&
971
oldState === newState &&
972
!hasContextChanged() &&
973
!checkHasForceUpdateAfterProcessing()
1064
cloneUpdateQueue(current, workInProgress);
1065
1066
const unresolvedOldProps = workInProgress.memoizedProps;
1055
- const oldProps =
1056
- workInProgress.type === workInProgress.elementType
1057
- ? unresolvedOldProps
1058
- : resolveDefaultProps(workInProgress.type, unresolvedOldProps);
1067
+ const oldProps = resolveClassComponentProps(
1068
+ ctor,
1069
+ unresolvedOldProps,
1070
+ workInProgress.type === workInProgress.elementType,
1071
+ );
1072
instance.props = oldProps;
1073
const unresolvedNewProps = workInProgress.pendingProps;
1074
1238
return shouldUpdate;
1239
}
1240
1241
+export function resolveClassComponentProps(
1242
+ Component: any,
1243
+ baseProps: Object,
1244
+ // Only resolve default props if this is a lazy component. Otherwise, they
1245
+ // would have already been resolved by the JSX runtime.
1246
+ // TODO: We're going to remove default prop resolution from the JSX runtime
1247
+ // and keep it only for class components. As part of that change, we should
1248
+ // remove this extra check.
1249
+ alreadyResolvedDefaultProps: boolean,
1250
+): Object {
1251
+ let newProps = baseProps;
1252
+
1253
+ // Resolve default props. Taken from old JSX runtime, where this used to live.
1254
+ const defaultProps = Component.defaultProps;
1255
+ if (defaultProps && !alreadyResolvedDefaultProps) {
1256
+ newProps = assign({}, newProps, baseProps);
1257
+ for (const propName in defaultProps) {
1258
+ if (newProps[propName] === undefined) {
1259
+ newProps[propName] = defaultProps[propName];
1260
+ }
1261
+ }
1262
+ }
1263
+
1264
+ if (enableRefAsProp) {
1265
+ // Remove ref from the props object, if it exists.
1266
+ if ('ref' in newProps) {
1267
+ if (newProps === baseProps) {
1268
+ newProps = assign({}, newProps);
1269
+ }
1270
+ delete newProps.ref;
1271
+ }
1272
+ }
1273
+
1274
+ return newProps;
1275
+}
1276
+
1277
export {
1278
constructClassInstance,
1279
mountClassInstance,