Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47340
This diff cleans up some problematic `React.ElementRef<T>` when T is generic type.
Changelog: [Internal]
Reviewed By: alexmckenley
Differential Revision: D65280467
fbshipit-source-id: 71172b16320a10cbc7a8b46dae5d3dd0eb00ba0c
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47109
Fixes the `lint/sort-imports` errors that are now surfaced after fixing the lint configuration.
For a couple files, I added lint suppressions instead because the unsorted import ordering is important due to interleaved calls with side effects.
Changelog:
[Internal]
Reviewed By: GijsWeterings
Differential Revision: D64569485
fbshipit-source-id: 26415d792e2b9efe08c05d1436f723faae549882
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/46990
This is a reattempt land D63643856 to fix the scroll onendreached event not firing.
Changelog:
[General][Fixed] - Fix onEndReached not being called when getItemLayout is present and we scroll past render window
Reviewed By: NickGerleman
Differential Revision: D64222424
fbshipit-source-id: 7e22f377d2f754beb39fff2b5c097cea350daa7e
Summary:
This diff reverts D63643856
`_highestMeasuredFrameIndex` is not properly invalidated causing issues with previous logic when data size shrinks.
bypass-github-export-checks
Changelog:
[General][Changed] - Revert "Fix onEndReached not being called when getItemLayout is present and we scroll past render window"
Reviewed By: NickGerleman
Differential Revision: D64009287
fbshipit-source-id: 8a21b57f5247fc743e65f9a730ff33a9a89d2bc1
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/46736
Copying the comment in code:
> We only call `onEndReached` after we render the last cell, but when getItemLayout is present, we can scroll past the last rendered cell, and never trigger a new layout or bounds change, so we need to check again after rendering more cells.
Changelog:
[General][Fixed] - Fix onEndReached not being called when getItemLayout is present and we scroll past render window
Reviewed By: yungsters
Differential Revision: D63643856
fbshipit-source-id: 9c53789cb15b225ceac353c37cbb67f7beeaf4fb
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/46487
Changelog: [General][Fixed] Fixed accuracy of FlatList estimations to determine what elements are visible in the rendering window.
This fixes a bug in FlatList where it thinks that some elements are visible in the rendering window, when they're not. Specifically, if a cell hasn't been laid out yet, it ignores all the information it already has on the ones that had, and estimates its position and offset based on the estimated size of the cells. In this case, if the first element has a larger offset because the list has a header, that offset is ignored in this case.
One observed result of this is that in a list where there's a header and a single cell that occupy the whole rendering window, FlatList thinks it needs to pre-render an additional element because the header is ignored.
Reviewed By: NickGerleman
Differential Revision: D62649060
fbshipit-source-id: 437bae79916707ca1d08784190508a9f7e36688e
Summary:
This change bumps the React Native version in main to 0.77
bypass-github-export-checks
## Changelog:
[General][Changed] - Bump main to 0.77-main
## Facebook:
generated by running `js1 publish react-native 0.77.0-main`
Reviewed By: cortinico
Differential Revision: D62575939
fbshipit-source-id: 6d239fca2eed6cfe51f8c37f78d8dc8730c18b8c
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/46103
Reducing the boundary of rerender of virtual lists. Previously with prop: "strictMode={true}" the VirtualizedList still re rendered each CellRenderer component. Because method getDerivedStateFromProps generated every time a new uniq state and the cells didn’t have a PureComponent. It helps to improve react performance for lists which have 5+ elements.
I reused recomended approach from react doc https://legacy.reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#what-about-memoization
changelog: [internal]
Optimizing CellRenderer of VirtualizedList
Reviewed By: NickGerleman, sammy-SC
Differential Revision: D61493434
fbshipit-source-id: 917a33e48bd2f18e8ac150e5701d2e7c45dbe879
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/45998
The exact `React.Element` type is deprecated and will be removed in a future version of Flow.
Changelog: [Internal]
Reviewed By: gkz
Differential Revision: D61205640
fbshipit-source-id: a029a3a46c7d8d9f94b0b931b991b2ce461151b2
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/45904
Flow will error on these dollar types soon. For all the ones changed here, they can all be further simplified.
Changelog: [Internal]
Reviewed By: gkz
Differential Revision: D60786768
fbshipit-source-id: e26bf0be1c4a933fc0bd8b59827e10cbd7242a83
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44990
Upgrades React Native and Relay to depend on React 19, which is currently published as release candidates. This is in preparation for React Native 0.75.
This will depend on updating open source renderers after [facebook/react#29903](https://github.com/facebook/react/pull/29903) is merged.
Changelog:
[General][Changed] - Upgrade to React 19
Reviewed By: robhogan
Differential Revision: D58625271
fbshipit-source-id: f9ad95b18716a9ce02f7cfbcc7248bdfb244c010
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/45002
There are a couple Jest unit test cases for `VirtualizedList-test.js` that require further investigation.
We believe that these are problems with Jest fake timers in the test and not with the component itself, so for now let's skip them so as to unblock the upgrade to React 19.
Changelog:
[Internal]
Reviewed By: robhogan
Differential Revision: D58656948
fbshipit-source-id: d52f3ad8277def6eae20cbbc11751d73b769d929
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44997
Wrap `VirtualizedList-test` uses of `react-test-renderer` in `act` as appropriate, so as to pass under current React and mostly pass under React 19, with further fixes to come.
Changelog: [Internal]
Reviewed By: robhogan
Differential Revision: D58649295
fbshipit-source-id: 5e0fa791d581fbf004a2ca7eaa5c4b4d9a15ddfe
Summary:
Migrate `VirtualizedSectionList-test` to use `act`-wrapping in prepation for React 19.
Avoid the `react-native/jest/renderer` abstractions as this is a separate package.
Changelog: [Internal]
Reviewed By: yungsters
Differential Revision: D58653558
fbshipit-source-id: 0e19fff5c3998fb00b71c3d07100a2064682cb4c
Summary:
Stacked on top of #28498 for test fixes.
### Don't Rethrow
When we started React it was 1:1 setState calls a series of renders and
if they error, it errors where the setState was called. Simple. However,
then batching came and the error actually got thrown somewhere else.
With concurrent mode, it's not even possible to get setState itself to
throw anymore.
In fact, all APIs that can rethrow out of React are executed either at
the root of the scheduler or inside a DOM event handler.
If you throw inside a React.startTransition callback that's sync, then
that will bubble out of the startTransition but if you throw inside an
async callback or a useTransition we now need to handle it at the hook
site. So in 19 we need to make all React.startTransition swallow the
error (and report them to reportError).
The only one remaining that can throw is flushSync but it doesn't really
make sense for it to throw at the callsite neither because batching.
Just because something rendered in this flush doesn't mean it was
rendered due to what was just scheduled and doesn't mean that it should
abort any of the remaining code afterwards. setState is fire and forget.
It's send an instruction elsewhere, it's not part of the current
imperative code.
Error boundaries never rethrow. Since you should really always have
error boundaries, most of the time, it wouldn't rethrow anyway.
Rethrowing also actually currently drops errors on the floor since we
can only rethrow the first error, so to avoid that we'd need to call
reportError anyway. This happens in RN events.
The other issue with rethrowing is that it logs an extra console.error.
Since we're not sure that user code will actually log it anywhere we
still log it too just like we do with errors inside error boundaries
which leads all of these to log twice.
The goal of this PR is to never rethrow out of React instead, errors
outside of error boundaries get logged to reportError. Event system
errors too.
### Breaking Changes
The main thing this affects is testing where you want to inspect the
errors thrown. To make it easier to port, if you're inside `act` we
track the error into act in an aggregate error and then rethrow it at
the root of `act`. Unlike before though, if you flush synchronously
inside of act it'll still continue until the end of act before
rethrowing.
I expect most user code breakages would be to migrate from `flushSync`
to `act` if you assert on throwing.
However, in the React repo we also have `internalAct` and the
`waitForThrow` helpers. Since these have to use public production
implementations we track these using the global onerror or process
uncaughtException. Unlike regular act, includes both event handler
errors and onRecoverableError by default too. Not just render/commit
errors. So I had to account for that in our tests.
We restore logging an extra log for uncaught errors after the main log
with the component stack in it. We use `console.warn`. This is not yet
ignorable if you preventDefault to the main error event. To avoid
confusion if you don't end up logging the error to console I just added
`An error occurred`.
### Polyfill
All browsers we support really supports `reportError` but not all test
and server environments do, so I implemented a polyfill for browser and
node in `shared/reportGlobalError`. I don't love that this is included
in all builds and gets duplicated into isomorphic even though it's not
actually needed in production. Maybe in the future we can require a
polyfill for this.
### Follow Ups
In a follow up, I'll make caught vs uncaught error handling be
configurable too.
---------
DiffTrain build for commit https://github.com/facebook/react/commit/6786563f3cbbc9b16d5a8187207b5bd904386e53.
Changelog:
[Internal]
Reviewed By: kassens
Differential Revision: D55408481
Pulled By: yungsters
fbshipit-source-id: 598aa306369e21cb3e93ad6041a87bfbaa9eef9e
Co-authored-by: Ricky Hanlon <rickhanlonii@gmail.com>
Summary:
Now that RN is providing TS type information, many of those .d.ts files depend on types from react. In modern packagemanagers (Ex: pnpm) types/react will not be available to RN since it does not declare it as a dependency.
I also noticed that the types for react-native-popup-menu-android appear to be pointing to the wrong location.
Add types/react as a peerDependency on the packages that have .d.ts files that import from React.
Add types/react to peerDependencyMeta with optional:true to prevent users not using TS from requiring types/react.
## Changelog:
[GENERAL] [ADDED] Added types/react as an optional peerDependency
Pull Request resolved: https://github.com/facebook/react-native/pull/43509
Reviewed By: cortinico
Differential Revision: D55225940
Pulled By: NickGerleman
fbshipit-source-id: 4cbab071928cb925baec45f55461559acc9a54e6
Summary:
Minor fix to package.json which newer version of npm warn about when publishing, after running `npm pkg fix -ws` on the workspace.
{F1470070110}
## Changelog: [Internal] npm pkg fix -ws
Pull Request resolved: https://github.com/facebook/react-native/pull/43519
Test Plan: eyescloseddog
Reviewed By: cortinico
Differential Revision: D55012872
Pulled By: blakef
fbshipit-source-id: ff3c63a3eefaf56d369219a3d4b32d44d6d842c9
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43458
The React sync in D54783723 was failing because some tests were relying on `console.error` being called as `console.error('Some message')` but it was refactored as `console.error('%s..', 'Some message')`, making them fail.
This fixes the tests by formatting the arguments passed to the console functions and checking against that instead.
Changelog: [internal]
Reviewed By: sammy-SC
Differential Revision: D54849485
fbshipit-source-id: 0648263614725ea3f9c95b9f9bb13005adae46eb
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43377
Fixes `VirtualizedList-test.js`, which assumes fake timers (e.g. using `jest.runAllTimers()` and `jest.runOnlyPendingTimers()`) but did not actually use fake timers.
Changelog:
[Internal]
Reviewed By: yungsters
Differential Revision: D54668281
fbshipit-source-id: b14757744bb7a21a4e5573053549c36178826021
Summary:
In setups with `pnpm` `react-native/virtualized-lists` gets bundled incorrectly because of the following error:
`Module not found: Error: Can't resolve 'react'`
As 'react' is used inside of the package, it should declared explicitly, instead of being a phantom dependency.
## Changelog:
[GENERAL] [FIXED] - Declare missing peer dependency `react`
Pull Request resolved: https://github.com/facebook/react-native/pull/42947
Test Plan: not needed
Reviewed By: NickGerleman
Differential Revision: D53617462
Pulled By: cortinico
fbshipit-source-id: 19a8fed94263646b0af93339d5c014e629dfa6b1
Summary:
Currently if the virtualized list content is small `onStartReached` won't be called initially when the list is mounted. This is because when the content is small `onEndReached` will be called initially preventing `onStartReached` from being called. In `_maybeCallOnEdgeReached` calling `onEndReached` and `onStartReached` are in the same conditional so they cannot both be triggered at once. To improve the consistency of `onStartReached` we should call both `onEndReached` and `onStartReached` if needed.
## Changelog:
[GENERAL] [FIXED] - Call onStartReached initially when list is small and `onEndReached` is called
Pull Request resolved: https://github.com/facebook/react-native/pull/42902
Test Plan:
I used this code to test in RN Tester (replace content of RNTesterAppShared.js)
```ts
import React, { useState, useEffect } from "react";
import { StyleSheet, FlatList, View, Text, TouchableOpacity } from "react-native";
function App() {
const [data, setData] = useState(generatePosts(4));
const [idCount, setIdCount] = useState(1);
const renderItem = ({ item }) => <Item data={item} />;
const keyExtractor = (item) => item.id.toString();
console.log("-------")
return (
<View style={{ flex: 1, marginVertical: 20 }}>
<FlatList
key={idCount}
data={data}
renderItem={renderItem}
keyExtractor={keyExtractor}
onEndReachedThreshold={0.05}
onEndReached={() => console.log("onEndReached")}
onStartReachedThreshold={0.05}
onStartReached={() => console.log("onStartReached")}
inverted
/>
<TouchableOpacity style={{height: 50, width: '100%', backgroundColor: 'purple'}} onPress={()=>{
setIdCount(state => state + 1)
setData(generatePosts(2))
}}><Text> Press</Text></TouchableOpacity>
</View>
);
}
function Item({ data }) {
return (
<View style={styles.item}>
<Text style={styles.title}>
{data.id} - {data.title}
</Text>
</View>
);
}
const styles = StyleSheet.create({
item: {
backgroundColor: "#f9c2ff",
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
},
title: {
fontSize: 24,
},
});
const generatePosts = (count, start = 0) => {
return Array.from({ length: count }, (_, i) => ({
title: `Title ${start + i + 1}`,
vote: 10,
id: start + i,
}));
};
export default App;
```
Before the change only onEndReached is called, after the change both onStartReached and onEndReached is called.
Reviewed By: sammy-SC
Differential Revision: D53518434
Pulled By: cipolleschi
fbshipit-source-id: bc34e0d4758df6d5833be7290e5a66efaf252ffd
Summary:
The previous typing of FlatList and VirtualizedList did not convey any information on the type of the items passed in to `onViewableItemsChanged`, but instead the type was set to `any`. This PR adds the type information.
I set a default type `any` for thy ViewToken, because the type is exported and not having it would be a breaking change if that type is used. Like this it gracefully falls back to the default behavior of the `any` type.
Notice: I don't know how typing in "flow" works, but the same "issue" seems to be in there as well. Maybe someone with more flow experience can fix that as well:
https://github.com/facebook/react-native/blob/ae42e0202de2c3db489caf63839fced7b52efc5d/packages/virtualized-lists/Lists/ViewabilityHelper.js#L19-L20
## Changelog:
[GENERAL] [FIXED] - Add type information for items of VirtualizedList in `onViewableItemsChanged` signature
[GENERAL] [FIXED] - Add type information for items of FlatList in `onViewableItemsChanged` signature
Pull Request resolved: https://github.com/facebook/react-native/pull/42773
Test Plan:
Without the changes, typecheck of the project was fine, but with the changes applied to the node_modules/react-native copy a type error was found:
```
$ npm run typecheck
> my-project@1.0.0 typecheck
> tsc --skipLibCheck
src/MyComponent.tsx:385:29 - error TS2345: Argument of type '(string | number)[]' is not assignable to parameter of type 'number[]'.
Type 'string | number' is not assignable to type 'number'.
Type 'string' is not assignable to type 'number'.
385 viewableItems
~~~~~~~~~~~~~
386 .filter(
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
Reviewed By: rozele
Differential Revision: D53276749
Pulled By: NickGerleman
fbshipit-source-id: 3fa5c65b388a59942c106286ac502a85c583da50
Summary:
The logic to constrain the last spacer size is incorrect in some cases where the spacer is the last spacer, but not the last section in the list.
For more context, the role of spacer constraining is explained in this comment:
```
// Without getItemLayout, we limit our tail spacer to the _highestMeasuredFrameIndex to
// prevent the user for hyperscrolling into un-measured area because otherwise content will
// likely jump around as it renders in above the viewport.
```
For example it is incorrect in the case where we have:
ITEMS
SPACER
ITEMS
In this case the spacer is not actually the tail spacer so the constraining is incorrectly appied.
This causes issues mainly when using `maintainVisibleContentPosition` since it will cause it to scroll to an incorrect position and then cause the view that was supposed to stay visible to be virtualized away.
## Changelog:
[GENERAL] [FIXED] - Fix last spacer constrain logic in VirtualizedList
Pull Request resolved: https://github.com/facebook/react-native/pull/41846
Test Plan:
Tested using https://gist.github.com/janicduplessis/b67d1fafc08ef848378263208ab93d4c in RN tester, before the change content will jump on first click on add items.
Tested using the same example and setting initial posts to 1000, then we can see our content view size is still constrained properly (see scrolling indicator as reference).
Reviewed By: yungsters
Differential Revision: D51964500
Pulled By: NickGerleman
fbshipit-source-id: 4465aa5a36c95466aef6571314973c1e2c9a0f2c
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/41381
Noticed that when scrolling VirtualizedList's CellRenderer was re-rendering due to `onCellFocusCapture` not having a stable identify. Change the interface to CellRenderer to pass in the `cellKey` in the callback to save on creating new callbacks.
Changelog: [Internal]
Reviewed By: sammy-SC
Differential Revision: D51112928
fbshipit-source-id: 3fcb974d9b5585403895746fbc45f2cf5a9fa6b1
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/41270
`scheduleCellsToRenderUpdate()` is called in response to new measurements, or component changes. It has logic to decide whether to immediately calculate new state, or to defer it until a later batched period.
It will not immediately update state if we don't yet have measurements for cells, but this condition is after another which calculates priority, relying on these measurements. These are garbage if we don't yet have measurements, and trigger an invariant violation in horizontal RTL.
This switches around the conditions, to avoid offset resolution if we don't yet have valid measurements.
I suspect some "hiPri" renders where cells shift are bugged right now when we update state in response to content size change, before we have new corresponding cell layouts.
Changelog:
[General][Fixed] - Bail on hiPri render on missing layout data before checking priority
Reviewed By: yungsters
Differential Revision: D50791506
fbshipit-source-id: 8dbffc37edd2a42f7842c0090d344dcd6f3e3c6d
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/41113
changelog: [internal]
We must prevent VirtualizedList._onContentSizeChange from being triggered by a conflicting bubbling onContentSizeChange event.
For TextInput, we change the event onContentSizeChange from bubbling to direct (https://github.com/facebook/react-native/commit/744fb4a0d23d15a40cd591e31f6c0f6cb3a7f06b). To make this safer, we need to filter out any `onContentSizeChange` event since we can't control 3rd party components from dispatching onContentSizeChange as bubbling event.
Reviewed By: NickGerleman
Differential Revision: D50451232
fbshipit-source-id: b7a446e4efc9c45024d37f35cb53f2fcbb28799f
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/41051
Strictifies flow to flow strict-local in files where doing that doesn't cause new flow errors.
Changelog: Internal
Reviewed By: yungsters
Differential Revision: D50369011
fbshipit-source-id: b4a5a26b839b7327a3178e6f5b35246dea365a38
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/39646
We can dramatically simplify this code and remove quirks/hacks, now that we can assume layout events are always fired top down.
Changelog: [Internal]
Reviewed By: yungsters
Differential Revision: D49628669
fbshipit-source-id: 7de5bbc4597eba1c59aaa7672c70e76d2786c7ef
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/39335
In RTL we must have scrollview content length in order to resolve cell metrics. This means that on Paper, where layout events are bottom up, we cannot immediately calculate viewability in response to cell metric changes, as we may not yet have an accurate length of laid out list content.
This change makes us defer calculation of viewability changes in this case via `setTimeout()`, to run in a single batch after the next layout events are fired.
---
We need container dimensions to resolve the right-edge relative child directions. It is tricky to do this at a guaranteed right time with onLayout model on Paper.
When we are laying out children, the first layout on Paper looks like:
1. Child is laid out
2. Container is laid out
However, we will never see container onLayout if a child layout does not change the dimensions of the parent container. This will be the common case of subsequent child layouts, where the spacer size was accurate.
I.e. we may or may not ever see content laid out, but can only rely on having both offsets be up to date if we trigger calculation after the container layout would have happened. This is not an issue on Fabric where layout events are fired top-down, or for the most common cases of VirtualizedList, where we run calculations in idle batches that will happen after layout is set, but ends up causing problems for two scenarios I didn't originally account for:
We may recalculate cells to render immediately instead scheduling a later update if the list thinks blanking is immediate (high priority render). This means we cannot do an immediate update in response to cell layout, but we can in response to events batched after layout events are all dispatched, or in worst case delay in Paper RTL.
We do not batch/schedule viewability calculations in response to cell layout in the same wasy as we do for calculating cells to render, but do need them to trigger recalculation.
The way less hacky, but much more invasive solution, that would simplify a lot of this, would be to include parentWidth and parentHeight in onLayout events for Paper (and Fabric for consistency), so that we don't need to rely on event ordering, or sometimes not firing. I thought this would be too much at first, if we didn't have other use-cases, but am more and more tempted to tear down a lot of what we have here to do that instead, since this is not going to be able to rely on useLayoutEffect or IntersectionObserver in today's VirtualizedList because it will need to support Paper for the forseeable future..
Changelog:
[General][Fixed] - Fix invariant violation when using viewability callbacks with horizontal RTL FlatList on Paper
Reviewed By: yungsters
Differential Revision: D49072963
fbshipit-source-id: accd33e2c50935bb67700d94820f6418f130fe08
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/39031
`UIScrollView` `contentOffset` is flow-relative, so `x` is relative to the right edge of the screen. This coordinate space disagrees with layout events, `scrollTo` coordinates, and other platforms.
This applies the same logic we use for inverting `scrollTo` coordinates to invert `contentOffset` in scroll events, in both Paper and Fabric. We then remove the iOS specific workaround we have in VirtualizedList.
I did not test `contentInset` as part of this, whose structure has explicit edges like `left` and `right`.
Changelog:
[iOS][Fixed] - Fix inverted `contentOffset` in scroll events in RTL
Reviewed By: rozele
Differential Revision: D48379915
fbshipit-source-id: 8a9cbb01608e79ef3b179a76fbe3997a0cd23845