@office-iss/react-native-win32 0.68.0-preview.2 → 0.69.0-preview.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/.flowconfig +3 -3
  2. package/CHANGELOG.json +386 -14
  3. package/CHANGELOG.md +159 -9
  4. package/IntegrationTests/BUCK +4 -1
  5. package/Libraries/ActionSheetIOS/ActionSheetIOS.js +7 -0
  6. package/Libraries/ActionSheetIOS/NativeActionSheetManager.js +1 -0
  7. package/Libraries/Alert/Alert.win32.js +1 -1
  8. package/Libraries/Animated/AnimatedImplementation.js +1 -1
  9. package/Libraries/Animated/NativeAnimatedHelper.js +55 -9
  10. package/Libraries/Animated/NativeAnimatedModule.js +1 -0
  11. package/Libraries/Animated/NativeAnimatedTurboModule.js +1 -0
  12. package/Libraries/Animated/animations/TimingAnimation.js +6 -11
  13. package/Libraries/Animated/createAnimatedComponent.js +2 -2
  14. package/Libraries/Animated/nodes/AnimatedColor.js +95 -29
  15. package/Libraries/Animated/nodes/AnimatedInterpolation.js +19 -22
  16. package/Libraries/Animated/nodes/AnimatedNode.js +2 -2
  17. package/Libraries/Animated/nodes/AnimatedValue.js +1 -1
  18. package/Libraries/AppState/AppState.js +1 -1
  19. package/Libraries/Blob/URL.js +7 -1
  20. package/Libraries/Components/Button.js +3 -0
  21. package/Libraries/Components/DatePickerAndroid/NativeDatePickerAndroid.js +5 -0
  22. package/Libraries/Components/Pressable/Pressable.js +3 -3
  23. package/Libraries/Components/Pressable/Pressable.win32.js +3 -3
  24. package/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js +47 -38
  25. package/Libraries/Components/ScrollView/ScrollContentViewNativeComponent.js +15 -7
  26. package/Libraries/Components/ScrollView/ScrollView.js +1 -1
  27. package/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +16 -3
  28. package/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +3 -1
  29. package/Libraries/Components/Slider/Slider.js +0 -2
  30. package/Libraries/Components/Slider/SliderNativeComponent.js +0 -1
  31. package/Libraries/Components/StatusBar/StatusBar.js +6 -1
  32. package/Libraries/Components/Switch/Switch.js +13 -2
  33. package/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js +114 -109
  34. package/Libraries/Components/TextInput/RCTMultilineTextInputNativeComponent.js +17 -9
  35. package/Libraries/Components/TextInput/RCTSingelineTextInputNativeComponent.js +13 -5
  36. package/Libraries/Components/TextInput/RCTTextInputViewConfig.js +10 -0
  37. package/Libraries/Components/TextInput/TextInput.js +1 -8
  38. package/Libraries/Components/TextInput/TextInputState.js +10 -2
  39. package/Libraries/Components/TextInput/TextInputState.win32.js +10 -2
  40. package/Libraries/Components/Touchable/Tests/TouchableWin32Test.js.map +1 -1
  41. package/Libraries/Components/Touchable/TouchableBounce.js +1 -0
  42. package/Libraries/Components/Touchable/TouchableHighlight.js +1 -0
  43. package/Libraries/Components/Touchable/TouchableNativeFeedback.js +1 -0
  44. package/Libraries/Components/Touchable/TouchableOpacity.js +7 -1
  45. package/Libraries/Components/Touchable/TouchableWin32.Props.d.ts +3 -1
  46. package/Libraries/Components/Touchable/TouchableWin32.Props.js.map +1 -1
  47. package/Libraries/Components/Touchable/TouchableWithoutFeedback.js +2 -0
  48. package/Libraries/Components/View/ReactNativeViewAttributes.js +1 -0
  49. package/Libraries/Components/View/ReactNativeViewAttributes.win32.js +1 -0
  50. package/Libraries/Components/View/View.win32.js +33 -1
  51. package/Libraries/Components/View/ViewNativeComponent.js +68 -8
  52. package/Libraries/Components/View/ViewPropTypes.js +36 -4
  53. package/Libraries/Components/View/ViewPropTypes.win32.js +36 -4
  54. package/Libraries/Components/View/ViewWin32.Props.d.ts +1 -1
  55. package/Libraries/Components/View/ViewWin32.Props.js.map +1 -1
  56. package/Libraries/Core/Devtools/parseHermesStack.js +1 -1
  57. package/Libraries/Core/ExceptionsManager.js +1 -1
  58. package/Libraries/Core/RawEventEmitter.js +38 -0
  59. package/Libraries/Core/ReactNativeVersion.js +2 -2
  60. package/Libraries/Core/polyfillPromise.js +32 -0
  61. package/Libraries/Core/setUpReactDevTools.js +3 -2
  62. package/Libraries/EventEmitter/NativeEventEmitter.js +3 -3
  63. package/Libraries/EventEmitter/RCTDeviceEventEmitter.js +2 -1
  64. package/Libraries/EventEmitter/__mocks__/NativeEventEmitter.js +3 -3
  65. package/Libraries/Events/CustomEvent.js +32 -0
  66. package/Libraries/Events/EventPolyfill.js +239 -0
  67. package/Libraries/Image/Image.android.js +0 -6
  68. package/Libraries/Image/Image.ios.js +0 -6
  69. package/Libraries/Image/Image.win32.js +2 -8
  70. package/Libraries/Image/ImageViewNativeComponent.js +18 -3
  71. package/Libraries/Image/TextInlineImageNativeComponent.js +23 -15
  72. package/Libraries/Image/resolveAssetSource.win32.js +1 -1
  73. package/Libraries/Inspector/Inspector.js +2 -4
  74. package/Libraries/Inspector/Inspector.win32.js +7 -9
  75. package/Libraries/Interaction/BridgeSpyStallHandler.js +4 -3
  76. package/Libraries/Interaction/InteractionManager.js +1 -12
  77. package/Libraries/Interaction/TaskQueue.js +5 -4
  78. package/Libraries/LayoutAnimation/LayoutAnimation.js +13 -0
  79. package/Libraries/Linking/Linking.js +1 -1
  80. package/Libraries/Lists/FlatList.js +27 -6
  81. package/Libraries/Lists/VirtualizedList.js +71 -55
  82. package/Libraries/Lists/VirtualizedListContext.js +7 -3
  83. package/Libraries/Lists/VirtualizedSectionList.js +2 -2
  84. package/Libraries/Lists/__tests__/{FillRateHelper-test.windows.js → FillRateHelper-test.js} +2 -2
  85. package/Libraries/Lists/__tests__/{FlatList-test.windows.js → FlatList-test.js} +2 -2
  86. package/Libraries/Lists/__tests__/{SectionList-test.windows.js → SectionList-test.js} +14 -14
  87. package/Libraries/Lists/__tests__/{VirtualizeUtils-test.windows.js → VirtualizeUtils-test.js} +3 -3
  88. package/Libraries/Lists/__tests__/{VirtualizedList-test.windows.js → VirtualizedList-test.js} +92 -43
  89. package/Libraries/Lists/__tests__/{VirtualizedSectionList-test.windows.js → VirtualizedSectionList-test.js} +16 -14
  90. package/Libraries/LogBox/Data/LogBoxData.js +2 -2
  91. package/Libraries/LogBox/Data/LogBoxLog.js +1 -1
  92. package/Libraries/LogBox/Data/LogBoxSymbolication.js +1 -1
  93. package/Libraries/LogBox/Data/parseLogBoxLog.js +1 -1
  94. package/Libraries/LogBox/LogBox.js +2 -21
  95. package/Libraries/LogBox/UI/LogBoxInspectorFooter.js +1 -0
  96. package/Libraries/LogBox/UI/LogBoxInspectorHeader.js +2 -1
  97. package/Libraries/NativeComponent/BaseViewConfig.android.js +295 -0
  98. package/Libraries/NativeComponent/BaseViewConfig.ios.js +333 -0
  99. package/Libraries/NativeComponent/BaseViewConfig.win32.js +334 -0
  100. package/Libraries/NativeComponent/NativeComponentRegistry.js +0 -2
  101. package/Libraries/NativeComponent/PlatformBaseViewConfig.js +24 -0
  102. package/Libraries/NativeComponent/StaticViewConfigValidator.js +7 -42
  103. package/Libraries/NativeComponent/ViewConfig.js +4 -4
  104. package/Libraries/NativeComponent/ViewConfigIgnore.js +54 -0
  105. package/Libraries/Network/FormData.js +7 -1
  106. package/Libraries/Network/RCTNetworking.win32.js +1 -1
  107. package/Libraries/Pressability/Pressability.js +115 -46
  108. package/Libraries/Pressability/Pressability.win32.js +174 -69
  109. package/Libraries/Pressability/PressabilityDebug.js +5 -9
  110. package/Libraries/PushNotificationIOS/NativePushNotificationManagerIOS.js +1 -0
  111. package/Libraries/ReactNative/AppContainer.js +1 -1
  112. package/Libraries/ReactNative/{DummyUIManager.js → BridgelessUIManager.js} +62 -40
  113. package/Libraries/ReactNative/PaperUIManager.win32.js +5 -5
  114. package/Libraries/ReactNative/ReactNativeFeatureFlags.js +39 -0
  115. package/Libraries/ReactNative/UIManager.js +2 -3
  116. package/Libraries/ReactNative/renderApplication.js +4 -0
  117. package/Libraries/ReactPrivate/ReactNativePrivateInterface.js +8 -0
  118. package/Libraries/Renderer/implementations/ReactFabric-dev.js +5908 -4906
  119. package/Libraries/Renderer/implementations/ReactFabric-prod.js +2100 -1918
  120. package/Libraries/Renderer/implementations/ReactFabric-profiling.js +2567 -2352
  121. package/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js +5610 -4844
  122. package/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js +1710 -1556
  123. package/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.js +1830 -1639
  124. package/Libraries/Renderer/shims/ReactNativeTypes.js +2 -1
  125. package/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js +2 -1
  126. package/Libraries/StyleSheet/EdgeInsetsPropType.js +4 -1
  127. package/Libraries/StyleSheet/StyleSheetTypes.js +59 -66
  128. package/Libraries/StyleSheet/normalizeColor.js +1 -1
  129. package/Libraries/StyleSheet/private/_StyleSheetTypesOverrides.js +15 -0
  130. package/Libraries/StyleSheet/private/_TransformStyle.js +53 -0
  131. package/Libraries/Text/Text.js +13 -7
  132. package/Libraries/Text/TextNativeComponent.js +2 -0
  133. package/Libraries/Text/TextNativeComponent.win32.js +2 -0
  134. package/Libraries/Text/TextProps.js +10 -0
  135. package/Libraries/Types/CoreEventTypes.js +13 -1
  136. package/Libraries/Types/CoreEventTypes.win32.js +26 -1
  137. package/Libraries/Utilities/Appearance.js +0 -8
  138. package/Libraries/Utilities/HMRClient.js +1 -1
  139. package/Libraries/Utilities/ReactNativeTestTools.js +1 -0
  140. package/Libraries/Utilities/codegenNativeComponent.js +17 -6
  141. package/Libraries/Utilities/stringifySafe.js +4 -1
  142. package/Libraries/Utilities/verifyComponentAttributeEquivalence.js +3 -3
  143. package/Libraries/WebSocket/WebSocket.js +1 -1
  144. package/Libraries/vendor/emitter/_EmitterSubscription.js +1 -1
  145. package/Libraries/vendor/emitter/_EventEmitter.js +1 -1
  146. package/Libraries/vendor/emitter/_EventSubscription.js +1 -1
  147. package/index.js +30 -25
  148. package/index.win32.js +30 -25
  149. package/jest/preprocessor.js +24 -107
  150. package/jest/preprocessor_DO_NOT_USE.js +122 -0
  151. package/metro.config.js +3 -47
  152. package/overrides.json +39 -46
  153. package/package.json +28 -26
  154. package/rntypes/index.d.ts +19 -7
  155. package/src/Libraries/Components/Touchable/Tests/TouchableWin32Test.tsx +1 -1
  156. package/src/Libraries/Components/Touchable/TouchableWin32.Props.tsx +3 -1
  157. package/src/Libraries/Components/View/ViewWin32.Props.ts +1 -0
  158. package/src/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap +427 -0
  159. package/src/Libraries/Lists/__tests__/__snapshots__/SectionList-test.js.snap +391 -0
  160. package/src/Libraries/Lists/__tests__/__snapshots__/VirtualizeUtils-test.js.snap +3 -0
  161. package/src/Libraries/Lists/__tests__/__snapshots__/VirtualizedList-test.js.snap +4565 -0
  162. package/src/Libraries/Lists/__tests__/__snapshots__/VirtualizedSectionList-test.js.snap +1153 -0
  163. package/src/rntypes/index.d.ts +19 -7
  164. package/typings-index.js +5 -1
  165. package/typings-index.js.map +1 -1
  166. package/Libraries/Components/SegmentedControlIOS/RCTSegmentedControlNativeComponent.js +0 -44
  167. package/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.android.js +0 -45
  168. package/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.ios.js +0 -123
  169. package/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.js +0 -45
  170. package/Libraries/Components/View/ReactNativeViewViewConfig.js +0 -360
  171. package/Libraries/Components/View/ReactNativeViewViewConfig.win32.js +0 -401
  172. package/Libraries/Components/View/ReactNativeViewViewConfigAndroid.js +0 -83
  173. package/Libraries/ReactNative/UIManagerInjection.js +0 -15
  174. package/Libraries/Renderer/implementations/ReactFabric-dev.fb.js +0 -24527
  175. package/Libraries/Renderer/implementations/ReactFabric-prod.fb.js +0 -8309
  176. package/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js +0 -8961
  177. package/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js +0 -24948
  178. package/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js +0 -8400
  179. package/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js +0 -9049
  180. package/flow/Promise.js +0 -47
@@ -19,6 +19,7 @@ const React = require('react');
19
19
  const ReactNative = require('../Renderer/shims/ReactNative');
20
20
  const StyleSheet = require('../StyleSheet/StyleSheet');
21
21
  const View = require('../Components/View/View');
22
+ const ReactNativeStyleAttributes = require('../Components/View/ReactNativeStyleAttributes');
22
23
 
23
24
  const invariant = require('invariant');
24
25
 
@@ -47,10 +48,7 @@ const renderers = findRenderers();
47
48
  // Required for React DevTools to view/edit React Native styles in Flipper.
48
49
  // Flipper doesn't inject these values when initializing DevTools.
49
50
  hook.resolveRNStyle = require('../StyleSheet/flattenStyle');
50
- const viewConfig = require('../Components/View/ReactNativeViewViewConfig');
51
- hook.nativeStyleEditorValidAttributes = Object.keys(
52
- viewConfig.validAttributes.style,
53
- );
51
+ hook.nativeStyleEditorValidAttributes = Object.keys(ReactNativeStyleAttributes);
54
52
 
55
53
  function findRenderers(): $ReadOnlyArray<ReactRenderer> {
56
54
  const allRenderers = Array.from(hook.renderers.values());
@@ -19,6 +19,7 @@ const React = require('react');
19
19
  const ReactNative = require('../Renderer/shims/ReactNative');
20
20
  const StyleSheet = require('../StyleSheet/StyleSheet');
21
21
  const View = require('../Components/View/View');
22
+ const ReactNativeStyleAttributes = require('../Components/View/ReactNativeStyleAttributes');
22
23
 
23
24
  const invariant = require('invariant');
24
25
 
@@ -49,10 +50,7 @@ const renderers = findRenderers();
49
50
  // Required for React DevTools to view/edit React Native styles in Flipper.
50
51
  // Flipper doesn't inject these values when initializing DevTools.
51
52
  hook.resolveRNStyle = require('../StyleSheet/flattenStyle');
52
- const viewConfig = require('../Components/View/ReactNativeViewViewConfig');
53
- hook.nativeStyleEditorValidAttributes = Object.keys(
54
- viewConfig.validAttributes.style,
55
- );
53
+ hook.nativeStyleEditorValidAttributes = Object.keys(ReactNativeStyleAttributes);
56
54
 
57
55
  function findRenderers(): $ReadOnlyArray<ReactRenderer> {
58
56
  const allRenderers = Array.from(hook.renderers.values());
@@ -77,7 +75,7 @@ function getInspectorDataForViewAtPoint(
77
75
  inspectedView,
78
76
  locationX,
79
77
  locationY,
80
- (viewData) => {
78
+ viewData => {
81
79
  // Only return with non-empty view data since only one renderer will have this view.
82
80
  if (viewData && viewData.hierarchy.length > 0) {
83
81
  callback(viewData);
@@ -137,7 +135,7 @@ class Inspector extends React.Component<
137
135
 
138
136
  componentWillUnmount() {
139
137
  if (this._subs) {
140
- this._subs.map((fn) => fn());
138
+ this._subs.map(fn => fn());
141
139
  }
142
140
  hook.off('react-devtools', this._attachToDevtools);
143
141
  this._setTouchedViewData = null;
@@ -222,7 +220,7 @@ class Inspector extends React.Component<
222
220
  }
223
221
 
224
222
  onTouchPoint(locationX: number, locationY: number) {
225
- this._setTouchedViewData = (viewData) => {
223
+ this._setTouchedViewData = viewData => {
226
224
  const {
227
225
  hierarchy,
228
226
  props,
@@ -263,7 +261,7 @@ class Inspector extends React.Component<
263
261
  this.state.inspectedView,
264
262
  locationX,
265
263
  locationY,
266
- (viewData) => {
264
+ viewData => {
267
265
  if (this._setTouchedViewData != null) {
268
266
  this._setTouchedViewData(viewData);
269
267
  this._setTouchedViewData = null;
@@ -290,7 +288,7 @@ class Inspector extends React.Component<
290
288
 
291
289
  setTouchTargeting(val: boolean) {
292
290
  PressabilityDebug.setEnabled(val);
293
- this.props.onRequestRerenderApp((inspectedView) => {
291
+ this.props.onRequestRerenderApp(inspectedView => {
294
292
  this.setState({inspectedView});
295
293
  });
296
294
  }
@@ -10,14 +10,15 @@
10
10
 
11
11
  'use strict';
12
12
 
13
+ import type {SpyData} from '../BatchedBridge/MessageQueue';
13
14
  const JSEventLoopWatchdog = require('./JSEventLoopWatchdog');
14
- const MessageQueue = require('../BatchedBridge/MessageQueue');
15
15
 
16
+ const MessageQueue = require('../BatchedBridge/MessageQueue');
16
17
  const infoLog = require('../Utilities/infoLog');
17
18
 
18
19
  const BridgeSpyStallHandler = {
19
20
  register: function () {
20
- let spyBuffer = [];
21
+ let spyBuffer: Array<SpyData> = [];
21
22
  MessageQueue.spy(data => {
22
23
  spyBuffer.push(data);
23
24
  });
@@ -27,7 +28,7 @@ const BridgeSpyStallHandler = {
27
28
  infoLog(
28
29
  spyBuffer.length + ' bridge messages during stall: ',
29
30
  spyBuffer.map(info => {
30
- let args = '<args>';
31
+ let args: string | Array<?string> = '<args>';
31
32
  try {
32
33
  args = JSON.stringify(info.args);
33
34
  } catch (e1) {
@@ -91,7 +91,6 @@ const InteractionManager = {
91
91
  onFulfill?: ?(void) => ?(Promise<U> | U),
92
92
  onReject?: ?(error: mixed) => ?(Promise<U> | U),
93
93
  ) => Promise<U>,
94
- done: () => void,
95
94
  cancel: () => void,
96
95
  ...
97
96
  } {
@@ -110,16 +109,6 @@ const InteractionManager = {
110
109
  return {
111
110
  // $FlowFixMe[method-unbinding] added when improving typing for this parameters
112
111
  then: promise.then.bind(promise),
113
- done: (...args) => {
114
- // $FlowFixMe[method-unbinding] added when improving typing for this parameters
115
- if (promise.done) {
116
- return promise.done(...args);
117
- } else {
118
- console.warn(
119
- 'Tried to call done when not supported by current Promise implementation.',
120
- );
121
- }
122
- },
123
112
  cancel: function () {
124
113
  _taskQueue.cancelTasks(tasks);
125
114
  },
@@ -165,7 +154,7 @@ const _interactionSet = new Set();
165
154
  const _addInteractionSet = new Set();
166
155
  const _deleteInteractionSet = new Set();
167
156
  const _taskQueue = new TaskQueue({onMoreTasks: _scheduleUpdate});
168
- let _nextUpdateHandle = 0;
157
+ let _nextUpdateHandle: $FlowFixMe | TimeoutID = 0;
169
158
  let _inc = 0;
170
159
  let _deadline = -1;
171
160
 
@@ -171,10 +171,11 @@ class TaskQueue {
171
171
  this.hasTasksToProcess() && this._onMoreTasks();
172
172
  })
173
173
  .catch(ex => {
174
- ex.message = `TaskQueue: Error resolving Promise in task ${task.name}: ${ex.message}`;
175
- throw ex;
176
- })
177
- .done();
174
+ setTimeout(() => {
175
+ ex.message = `TaskQueue: Error resolving Promise in task ${task.name}: ${ex.message}`;
176
+ throw ex;
177
+ }, 0);
178
+ });
178
179
  }
179
180
  }
180
181
 
@@ -19,6 +19,7 @@ import type {
19
19
  } from '../Renderer/shims/ReactNativeTypes';
20
20
 
21
21
  import Platform from '../Utilities/Platform';
22
+ import ReactNativeFeatureFlags from '../ReactNative/ReactNativeFeatureFlags';
22
23
 
23
24
  // Reexport type
24
25
  export type LayoutAnimationConfig = LayoutAnimationConfig_;
@@ -26,6 +27,13 @@ export type LayoutAnimationConfig = LayoutAnimationConfig_;
26
27
  type OnAnimationDidEndCallback = () => void;
27
28
  type OnAnimationDidFailCallback = () => void;
28
29
 
30
+ let isLayoutAnimationEnabled: boolean =
31
+ ReactNativeFeatureFlags.isLayoutAnimationEnabled();
32
+
33
+ function setEnabled(value: boolean) {
34
+ isLayoutAnimationEnabled = isLayoutAnimationEnabled;
35
+ }
36
+
29
37
  /**
30
38
  * Configures the next commit to be animated.
31
39
  *
@@ -43,6 +51,10 @@ function configureNext(
43
51
  return;
44
52
  }
45
53
 
54
+ if (!isLayoutAnimationEnabled) {
55
+ return;
56
+ }
57
+
46
58
  // Since LayoutAnimations may possibly be disabled for now on iOS (Fabric),
47
59
  // or Android (non-Fabric) we race a setTimeout with animation completion,
48
60
  // in case onComplete is never called
@@ -181,6 +193,7 @@ const LayoutAnimation = {
181
193
  spring: (configureNext.bind(null, Presets.spring): (
182
194
  onAnimationDidEnd?: OnAnimationDidEndCallback,
183
195
  ) => void),
196
+ setEnabled,
184
197
  };
185
198
 
186
199
  module.exports = LayoutAnimation;
@@ -8,7 +8,7 @@
8
8
  * @flow strict-local
9
9
  */
10
10
 
11
- import {type EventSubscription} from '../vendor/emitter/EventEmitter';
11
+ import type {EventSubscription} from '../vendor/emitter/EventEmitter';
12
12
  import NativeEventEmitter from '../EventEmitter/NativeEventEmitter';
13
13
  import InteractionManager from '../Interaction/InteractionManager';
14
14
  import Platform from '../Utilities/Platform';
@@ -26,6 +26,7 @@ import type {
26
26
  } from './ViewabilityHelper';
27
27
  import type {RenderItemType, RenderItemProps} from './VirtualizedList';
28
28
  import {keyExtractor as defaultKeyExtractor} from './VirtualizeUtils';
29
+ import memoizeOne from 'memoize-one';
29
30
 
30
31
  type RequiredProps<ItemT> = {|
31
32
  /**
@@ -141,6 +142,10 @@ type OptionalProps<ItemT> = {|
141
142
  * See `ScrollView` for flow type and further documentation.
142
143
  */
143
144
  fadingEdgeLength?: ?number,
145
+ /**
146
+ * Enable an optimization to memoize the item renderer to prevent unnecessary rerenders.
147
+ */
148
+ strictMode?: boolean,
144
149
  |};
145
150
 
146
151
  /**
@@ -578,9 +583,14 @@ class FlatList<ItemT> extends React.PureComponent<Props<ItemT>, void> {
578
583
  };
579
584
  }
580
585
 
581
- _renderer = () => {
582
- const {ListItemComponent, renderItem, columnWrapperStyle} = this.props;
583
- const numColumns = numColumnsOrDefault(this.props.numColumns);
586
+ _renderer = (
587
+ ListItemComponent: ?(React.ComponentType<any> | React.Element<any>),
588
+ renderItem: ?RenderItemType<ItemT>,
589
+ columnWrapperStyle: ?ViewStyleProp,
590
+ numColumns: ?number,
591
+ extraData: ?any,
592
+ ) => {
593
+ const cols = numColumnsOrDefault(numColumns);
584
594
 
585
595
  let virtualizedListRenderKey = ListItemComponent
586
596
  ? 'ListItemComponent'
@@ -605,7 +615,7 @@ class FlatList<ItemT> extends React.PureComponent<Props<ItemT>, void> {
605
615
  * This comment suppresses an error found when Flow v0.111 was deployed.
606
616
  * To see the error, delete this comment and run Flow. */
607
617
  [virtualizedListRenderKey]: (info: RenderItemProps<ItemT>) => {
608
- if (numColumns > 1) {
618
+ if (cols > 1) {
609
619
  const {item, index} = info;
610
620
  invariant(
611
621
  Array.isArray(item),
@@ -616,7 +626,7 @@ class FlatList<ItemT> extends React.PureComponent<Props<ItemT>, void> {
616
626
  {item.map((it, kk) => {
617
627
  const element = renderer({
618
628
  item: it,
619
- index: index * numColumns + kk,
629
+ index: index * cols + kk,
620
630
  separators: info.separators,
621
631
  });
622
632
  return element != null ? (
@@ -632,14 +642,19 @@ class FlatList<ItemT> extends React.PureComponent<Props<ItemT>, void> {
632
642
  };
633
643
  };
634
644
 
645
+ _memoizedRenderer = memoizeOne(this._renderer);
646
+
635
647
  render(): React.Node {
636
648
  const {
637
649
  numColumns,
638
650
  columnWrapperStyle,
639
651
  removeClippedSubviews: _removeClippedSubviews,
652
+ strictMode = false,
640
653
  ...restProps
641
654
  } = this.props;
642
655
 
656
+ const renderer = strictMode ? this._memoizedRenderer : this._renderer;
657
+
643
658
  return (
644
659
  <VirtualizedList
645
660
  {...restProps}
@@ -651,7 +666,13 @@ class FlatList<ItemT> extends React.PureComponent<Props<ItemT>, void> {
651
666
  removeClippedSubviews={removeClippedSubviewsOrDefault(
652
667
  _removeClippedSubviews,
653
668
  )}
654
- {...this._renderer()}
669
+ {...renderer(
670
+ this.props.ListItemComponent,
671
+ this.props.renderItem,
672
+ columnWrapperStyle,
673
+ numColumns,
674
+ this.props.extraData,
675
+ )}
655
676
  />
656
677
  );
657
678
  }
@@ -34,6 +34,7 @@ import type {
34
34
  ViewToken,
35
35
  ViewabilityConfigCallbackPair,
36
36
  } from './ViewabilityHelper';
37
+ import type {LayoutEvent} from '../Types/CoreEventTypes';
37
38
  import {
38
39
  VirtualizedListCellContextProvider,
39
40
  VirtualizedListContext,
@@ -384,7 +385,7 @@ class VirtualizedList extends React.PureComponent<Props, State> {
384
385
  scrollToEnd(params?: ?{animated?: ?boolean, ...}) {
385
386
  const animated = params ? params.animated : true;
386
387
  const veryLast = this.props.getItemCount(this.props.data) - 1;
387
- const frame = this._getFrameMetricsApprox(veryLast);
388
+ const frame = this.__getFrameMetricsApprox(veryLast);
388
389
  const offset = Math.max(
389
390
  0,
390
391
  frame.offset +
@@ -458,7 +459,7 @@ class VirtualizedList extends React.PureComponent<Props, State> {
458
459
  });
459
460
  return;
460
461
  }
461
- const frame = this._getFrameMetricsApprox(index);
462
+ const frame = this.__getFrameMetricsApprox(index);
462
463
  const offset =
463
464
  Math.max(
464
465
  0,
@@ -796,12 +797,17 @@ class VirtualizedList extends React.PureComponent<Props, State> {
796
797
  const {
797
798
  CellRendererComponent,
798
799
  ItemSeparatorComponent,
800
+ ListHeaderComponent,
801
+ ListItemComponent,
799
802
  data,
803
+ debug,
800
804
  getItem,
801
805
  getItemCount,
806
+ getItemLayout,
802
807
  horizontal,
808
+ renderItem,
803
809
  } = this.props;
804
- const stickyOffset = this.props.ListHeaderComponent ? 1 : 0;
810
+ const stickyOffset = ListHeaderComponent ? 1 : 0;
805
811
  const end = getItemCount(data) - 1;
806
812
  let prevCellKey;
807
813
  last = Math.min(end, last);
@@ -816,21 +822,24 @@ class VirtualizedList extends React.PureComponent<Props, State> {
816
822
  <CellRenderer
817
823
  CellRendererComponent={CellRendererComponent}
818
824
  ItemSeparatorComponent={ii < end ? ItemSeparatorComponent : undefined}
825
+ ListItemComponent={ListItemComponent}
819
826
  cellKey={key}
827
+ debug={debug}
820
828
  fillRateHelper={this._fillRateHelper}
829
+ getItemLayout={getItemLayout}
821
830
  horizontal={horizontal}
822
831
  index={ii}
823
832
  inversionStyle={inversionStyle}
824
833
  item={item}
825
834
  key={key}
826
835
  prevCellKey={prevCellKey}
836
+ onCellLayout={this._onCellLayout}
827
837
  onUpdateSeparators={this._onUpdateSeparators}
828
- onLayout={e => this._onCellLayout(e, key, ii)}
829
838
  onUnmount={this._onCellUnmount}
830
- parentProps={this.props}
831
839
  ref={ref => {
832
840
  this._cellRefs[key] = ref;
833
841
  }}
842
+ renderItem={renderItem}
834
843
  />,
835
844
  );
836
845
  prevCellKey = key;
@@ -950,8 +959,8 @@ class VirtualizedList extends React.PureComponent<Props, State> {
950
959
  // See if there are any sticky headers in the virtualized space that we need to render.
951
960
  for (let ii = firstAfterInitial - 1; ii > lastInitialIndex; ii--) {
952
961
  if (stickyIndicesFromProps.has(ii + stickyOffset)) {
953
- const initBlock = this._getFrameMetricsApprox(lastInitialIndex);
954
- const stickyBlock = this._getFrameMetricsApprox(ii);
962
+ const initBlock = this.__getFrameMetricsApprox(lastInitialIndex);
963
+ const stickyBlock = this.__getFrameMetricsApprox(ii);
955
964
  const leadSpace =
956
965
  stickyBlock.offset -
957
966
  initBlock.offset -
@@ -968,7 +977,7 @@ class VirtualizedList extends React.PureComponent<Props, State> {
968
977
  inversionStyle,
969
978
  );
970
979
  const trailSpace =
971
- this._getFrameMetricsApprox(first).offset -
980
+ this.__getFrameMetricsApprox(first).offset -
972
981
  (stickyBlock.offset + stickyBlock.length);
973
982
  cells.push(
974
983
  <View key="$sticky_trail" style={{[spacerKey]: trailSpace}} />,
@@ -979,9 +988,9 @@ class VirtualizedList extends React.PureComponent<Props, State> {
979
988
  }
980
989
  }
981
990
  if (!insertedStickySpacer) {
982
- const initBlock = this._getFrameMetricsApprox(lastInitialIndex);
991
+ const initBlock = this.__getFrameMetricsApprox(lastInitialIndex);
983
992
  const firstSpace =
984
- this._getFrameMetricsApprox(first).offset -
993
+ this.__getFrameMetricsApprox(first).offset -
985
994
  (initBlock.offset + initBlock.length);
986
995
  cells.push(
987
996
  <View key="$lead_spacer" style={{[spacerKey]: firstSpace}} />,
@@ -1005,14 +1014,14 @@ class VirtualizedList extends React.PureComponent<Props, State> {
1005
1014
  this._hasWarned.keys = true;
1006
1015
  }
1007
1016
  if (!isVirtualizationDisabled && last < itemCount - 1) {
1008
- const lastFrame = this._getFrameMetricsApprox(last);
1017
+ const lastFrame = this.__getFrameMetricsApprox(last);
1009
1018
  // Without getItemLayout, we limit our tail spacer to the _highestMeasuredFrameIndex to
1010
1019
  // prevent the user for hyperscrolling into un-measured area because otherwise content will
1011
1020
  // likely jump around as it renders in above the viewport.
1012
1021
  const end = this.props.getItemLayout
1013
1022
  ? itemCount - 1
1014
1023
  : Math.min(itemCount - 1, this._highestMeasuredFrameIndex);
1015
- const endFrame = this._getFrameMetricsApprox(end);
1024
+ const endFrame = this.__getFrameMetricsApprox(end);
1016
1025
  const tailSpacerLength =
1017
1026
  endFrame.offset +
1018
1027
  endFrame.length -
@@ -1119,7 +1128,7 @@ class VirtualizedList extends React.PureComponent<Props, State> {
1119
1128
  )}
1120
1129
  </VirtualizedListContextProvider>
1121
1130
  );
1122
- let ret = innerRet;
1131
+ let ret: React.Node = innerRet;
1123
1132
  if (__DEV__) {
1124
1133
  ret = (
1125
1134
  <ScrollView.Context.Consumer>
@@ -1268,7 +1277,7 @@ class VirtualizedList extends React.PureComponent<Props, State> {
1268
1277
  }
1269
1278
  };
1270
1279
 
1271
- _onCellLayout(e, cellKey, index) {
1280
+ _onCellLayout = (e: LayoutEvent, cellKey: string, index: number): void => {
1272
1281
  const layout = e.nativeEvent.layout;
1273
1282
  const next = {
1274
1283
  offset: this._selectOffset(layout),
@@ -1301,7 +1310,7 @@ class VirtualizedList extends React.PureComponent<Props, State> {
1301
1310
 
1302
1311
  this._computeBlankness();
1303
1312
  this._updateViewableItems(this.props.data);
1304
- }
1313
+ };
1305
1314
 
1306
1315
  _onCellUnmount = (cellKey: string) => {
1307
1316
  const curr = this._frames[cellKey];
@@ -1380,7 +1389,7 @@ class VirtualizedList extends React.PureComponent<Props, State> {
1380
1389
  }
1381
1390
  }
1382
1391
 
1383
- _onLayout = (e: Object) => {
1392
+ _onLayout = (e: LayoutEvent) => {
1384
1393
  if (this._isNestedWithSameOrientation()) {
1385
1394
  // Need to adjust our scroll metrics to be relative to our containing
1386
1395
  // VirtualizedList before we can make claims about list item viewability
@@ -1395,7 +1404,7 @@ class VirtualizedList extends React.PureComponent<Props, State> {
1395
1404
  this._maybeCallOnEndReached();
1396
1405
  };
1397
1406
 
1398
- _onLayoutEmpty = e => {
1407
+ _onLayoutEmpty = (e: LayoutEvent) => {
1399
1408
  this.props.onLayout && this.props.onLayout(e);
1400
1409
  };
1401
1410
 
@@ -1403,12 +1412,12 @@ class VirtualizedList extends React.PureComponent<Props, State> {
1403
1412
  return this._getCellKey() + '-footer';
1404
1413
  }
1405
1414
 
1406
- _onLayoutFooter = e => {
1415
+ _onLayoutFooter = (e: LayoutEvent) => {
1407
1416
  this._triggerRemeasureForChildListsInCell(this._getFooterCellKey());
1408
1417
  this._footerLength = this._selectLength(e.nativeEvent.layout);
1409
1418
  };
1410
1419
 
1411
- _onLayoutHeader = e => {
1420
+ _onLayoutHeader = (e: LayoutEvent) => {
1412
1421
  this._headerLength = this._selectLength(e.nativeEvent.layout);
1413
1422
  };
1414
1423
 
@@ -1419,7 +1428,7 @@ class VirtualizedList extends React.PureComponent<Props, State> {
1419
1428
  const framesInLayout = [];
1420
1429
  const itemCount = this.props.getItemCount(this.props.data);
1421
1430
  for (let ii = 0; ii < itemCount; ii++) {
1422
- const frame = this._getFrameMetricsApprox(ii);
1431
+ const frame = this.__getFrameMetricsApprox(ii);
1423
1432
  /* $FlowFixMe[prop-missing] (>=0.68.0 site=react_native_fb) This comment
1424
1433
  * suppresses an error found when Flow v0.68 was deployed. To see the
1425
1434
  * error delete this comment and run Flow. */
@@ -1427,8 +1436,8 @@ class VirtualizedList extends React.PureComponent<Props, State> {
1427
1436
  framesInLayout.push(frame);
1428
1437
  }
1429
1438
  }
1430
- const windowTop = this._getFrameMetricsApprox(this.state.first).offset;
1431
- const frameLast = this._getFrameMetricsApprox(this.state.last);
1439
+ const windowTop = this.__getFrameMetricsApprox(this.state.first).offset;
1440
+ const frameLast = this.__getFrameMetricsApprox(this.state.last);
1432
1441
  const windowLen = frameLast.offset + frameLast.length - windowTop;
1433
1442
  const visTop = this._scrollMetrics.offset;
1434
1443
  const visLen = this._scrollMetrics.visibleLength;
@@ -1642,7 +1651,7 @@ class VirtualizedList extends React.PureComponent<Props, State> {
1642
1651
  // Mark as high priority if we're close to the start of the first item
1643
1652
  // But only if there are items before the first rendered item
1644
1653
  if (first > 0) {
1645
- const distTop = offset - this._getFrameMetricsApprox(first).offset;
1654
+ const distTop = offset - this.__getFrameMetricsApprox(first).offset;
1646
1655
  hiPri =
1647
1656
  hiPri || distTop < 0 || (velocity < -2 && distTop < scrollingThreshold);
1648
1657
  }
@@ -1650,7 +1659,7 @@ class VirtualizedList extends React.PureComponent<Props, State> {
1650
1659
  // But only if there are items after the last rendered item
1651
1660
  if (last < itemCount - 1) {
1652
1661
  const distBottom =
1653
- this._getFrameMetricsApprox(last).offset - (offset + visibleLength);
1662
+ this.__getFrameMetricsApprox(last).offset - (offset + visibleLength);
1654
1663
  hiPri =
1655
1664
  hiPri ||
1656
1665
  distBottom < 0 ||
@@ -1733,7 +1742,10 @@ class VirtualizedList extends React.PureComponent<Props, State> {
1733
1742
  return;
1734
1743
  }
1735
1744
  this.setState(state => {
1736
- let newState;
1745
+ let newState: ?(
1746
+ | {first: number, last: number, ...}
1747
+ | $TEMPORARY$object<{first: number, last: number}>
1748
+ );
1737
1749
  const {contentLength, offset, visibleLength} = this._scrollMetrics;
1738
1750
  if (!isVirtualizationDisabled) {
1739
1751
  // If we run this with bogus data, we'll force-render window {first: 0, last: 0},
@@ -1745,14 +1757,14 @@ class VirtualizedList extends React.PureComponent<Props, State> {
1745
1757
  // we'll wipe out the initialNumToRender rendered elements starting at initialScrollIndex.
1746
1758
  // So let's wait until we've scrolled the view to the right place. And until then,
1747
1759
  // we will trust the initialScrollIndex suggestion.
1748
- if (!this.props.initialScrollIndex || this._scrollMetrics.offset) {
1760
+ if (!this.props.initialScrollIndex || this._hasDoneInitialScroll) {
1749
1761
  newState = computeWindowedRenderLimits(
1750
1762
  this.props.data,
1751
1763
  this.props.getItemCount,
1752
1764
  maxToRenderPerBatchOrDefault(this.props.maxToRenderPerBatch),
1753
1765
  windowSizeOrDefault(this.props.windowSize),
1754
1766
  state,
1755
- this._getFrameMetricsApprox,
1767
+ this.__getFrameMetricsApprox,
1756
1768
  this._scrollMetrics,
1757
1769
  );
1758
1770
  }
@@ -1815,13 +1827,11 @@ class VirtualizedList extends React.PureComponent<Props, State> {
1815
1827
  return {index, item, key: this._keyExtractor(item, index), isViewable};
1816
1828
  };
1817
1829
 
1818
- _getFrameMetricsApprox = (
1819
- index: number,
1820
- ): {
1830
+ __getFrameMetricsApprox: (index: number) => {
1821
1831
  length: number,
1822
1832
  offset: number,
1823
1833
  ...
1824
- } => {
1834
+ } = index => {
1825
1835
  const frame = this._getFrameMetrics(index);
1826
1836
  if (frame && frame.index === index) {
1827
1837
  // check for invalid frames due to row re-ordering
@@ -1888,32 +1898,29 @@ type CellRendererProps = {
1888
1898
  ItemSeparatorComponent: ?React.ComponentType<
1889
1899
  any | {highlighted: boolean, leadingItem: ?Item},
1890
1900
  >,
1901
+ ListItemComponent?: ?(React.ComponentType<any> | React.Element<any>),
1891
1902
  cellKey: string,
1903
+ debug?: ?boolean,
1892
1904
  fillRateHelper: FillRateHelper,
1905
+ getItemLayout?: (
1906
+ data: any,
1907
+ index: number,
1908
+ ) => {
1909
+ length: number,
1910
+ offset: number,
1911
+ index: number,
1912
+ ...
1913
+ },
1893
1914
  horizontal: ?boolean,
1894
1915
  index: number,
1895
1916
  inversionStyle: ViewStyleProp,
1896
1917
  item: Item,
1897
1918
  // This is extracted by ScrollViewStickyHeader
1898
- onLayout: (event: Object) => void,
1919
+ onCellLayout: (event: Object, cellKey: string, index: number) => void,
1899
1920
  onUnmount: (cellKey: string) => void,
1900
1921
  onUpdateSeparators: (cellKeys: Array<?string>, props: Object) => void,
1901
- parentProps: {
1902
- // e.g. height, y,
1903
- getItemLayout?: (
1904
- data: any,
1905
- index: number,
1906
- ) => {
1907
- length: number,
1908
- offset: number,
1909
- index: number,
1910
- ...
1911
- },
1912
- renderItem?: ?RenderItemType<Item>,
1913
- ListItemComponent?: ?(React.ComponentType<any> | React.Element<any>),
1914
- ...
1915
- },
1916
1922
  prevCellKey: ?string,
1923
+ renderItem?: ?RenderItemType<Item>,
1917
1924
  ...
1918
1925
  };
1919
1926
 
@@ -1982,6 +1989,15 @@ class CellRenderer extends React.Component<
1982
1989
  this.props.onUnmount(this.props.cellKey);
1983
1990
  }
1984
1991
 
1992
+ _onLayout = (nativeEvent: LayoutEvent): void => {
1993
+ this.props.onCellLayout &&
1994
+ this.props.onCellLayout(
1995
+ nativeEvent,
1996
+ this.props.cellKey,
1997
+ this.props.index,
1998
+ );
1999
+ };
2000
+
1985
2001
  _renderElement(renderItem, ListItemComponent, item, index) {
1986
2002
  if (renderItem && ListItemComponent) {
1987
2003
  console.warn(
@@ -2022,14 +2038,16 @@ class CellRenderer extends React.Component<
2022
2038
  const {
2023
2039
  CellRendererComponent,
2024
2040
  ItemSeparatorComponent,
2041
+ ListItemComponent,
2042
+ debug,
2025
2043
  fillRateHelper,
2044
+ getItemLayout,
2026
2045
  horizontal,
2027
2046
  item,
2028
2047
  index,
2029
2048
  inversionStyle,
2030
- parentProps,
2049
+ renderItem,
2031
2050
  } = this.props;
2032
- const {renderItem, getItemLayout, ListItemComponent} = parentProps;
2033
2051
  const element = this._renderElement(
2034
2052
  renderItem,
2035
2053
  ListItemComponent,
@@ -2038,12 +2056,10 @@ class CellRenderer extends React.Component<
2038
2056
  );
2039
2057
 
2040
2058
  const onLayout =
2041
- /* $FlowFixMe[prop-missing] (>=0.68.0 site=react_native_fb) This comment
2042
- * suppresses an error found when Flow v0.68 was deployed. To see the
2043
- * error delete this comment and run Flow. */
2044
- getItemLayout && !parentProps.debug && !fillRateHelper.enabled()
2059
+ (getItemLayout && !debug && !fillRateHelper.enabled()) ||
2060
+ !this.props.onCellLayout
2045
2061
  ? undefined
2046
- : this.props.onLayout;
2062
+ : this._onLayout;
2047
2063
  // NOTE: that when this is a sticky header, `onLayout` will get automatically extracted and
2048
2064
  // called explicitly by `ScrollViewStickyHeader`.
2049
2065
  const itemSeparator = ItemSeparatorComponent && (
@@ -2096,7 +2112,7 @@ function describeNestedLists(childList: {
2096
2112
  ` listKey: ${childList.key}\n` +
2097
2113
  ` cellKey: ${childList.cellKey}`;
2098
2114
 
2099
- let debugInfo = childList.parentDebugInfo;
2115
+ let debugInfo: ?ListDebugInfo = childList.parentDebugInfo;
2100
2116
  while (debugInfo) {
2101
2117
  trace +=
2102
2118
  `\n Parent (${debugInfo.horizontal ? 'horizontal' : 'vertical'}):\n` +
@@ -142,10 +142,14 @@ export function VirtualizedListCellContextProvider({
142
142
  cellKey: string,
143
143
  children: React.Node,
144
144
  }): React.Node {
145
- const context = useContext(VirtualizedListContext);
145
+ // Avoid setting a newly created context object if the values are identical.
146
+ const currContext = useContext(VirtualizedListContext);
147
+ const context = useMemo(
148
+ () => (currContext == null ? null : {...currContext, cellKey}),
149
+ [currContext, cellKey],
150
+ );
146
151
  return (
147
- <VirtualizedListContext.Provider
148
- value={context == null ? null : {...context, cellKey}}>
152
+ <VirtualizedListContext.Provider value={context}>
149
153
  {children}
150
154
  </VirtualizedListContext.Provider>
151
155
  );