Summary:
We ran into a problem trying to style the optional prop `ListHeaderComponent` in the `FlatList` library component. Essentially we wanted to make `ListHeaderComponent` a flex item that filled all of the empty space in the list if there was any. Unfortunately the `ListHeaderComponent` is later wrapped in a `View` that blocked our styling. The `View` component was necessary as it added styling to handle inverting the `FlatList`. Similarly `ListFooterComponent` was handled the same way.
We came up the simple solution of adding two new optional props, `ListHeaderComponentStyle` and `ListFooterComponentStyle`, that are of type `ViewStyleProp` that allow users to pass in styling for `ListHeaderComponent` and `ListFooterComponent`.
With this change we were able to do something like the following to get the header component to fill all empty space in the `FlatList`.
```
<FlatList
...
contentContainerStyle={{flexGrow: 1}}
ListHeaderComponent={<View style={{flex: 1}} />}
ListHeaderComponentStyle={{flexGrow: 1}}
...
/>
```
This solution will give users a lot more freedom when working with headers and footers.
Reviewed By: sahrens
Differential Revision: D8777038
fbshipit-source-id: f34116ce68548ea70223e639d0f84a099327f6b3
Summary:
Jest will now exclude undefined props from snapshots (https://github.com/facebook/jest/pull/6162). Updating the snapshots should fix the current `test_javascript` failures.
Circle CI
[INTERNAL][MINOR][Snapshots] - Update snapshots
Closes https://github.com/facebook/react-native/pull/19414
Differential Revision: D8125193
Pulled By: hramos
fbshipit-source-id: db8dcfcd8afbf9d6256f83c6e922680a7872d776
Summary:
StrictMode compliance is important for Async Rendering and other Future Tech(tm).
Also clean up some lint.
== Test Plan ==
* No more StrictMode warnings for `FlatList` (`VirtualizedList` is another story....).
* props warnings still show up when appropriate.
Reviewed By: sophiebits
Differential Revision: D8026333
fbshipit-source-id: e6fa2f02d546b883df6f3cff8776c26c6ef91bc9
Summary:
A common UI pattern for list empty states is some text/images centered inside the visible part of the list. This is pretty hard to do currently because we wrap ListEmptyComponent with an extra view with no way to style it so we cannot just use `flex: 1` to make it fill the available space.
- Added an example of ListEmptyComponent in the FlatList example in RNTester
Before (no way to make ListEmptyComponent fill the space):
<img width="377" alt="screen shot 2018-03-05 at 5 24 15 pm" src="https://user-images.githubusercontent.com/2677334/37003152-129db3ac-209a-11e8-9600-110f10d57144.png">
After:
<img width="377" alt="screen shot 2018-03-05 at 5 09 20 pm" src="https://user-images.githubusercontent.com/2677334/37002809-e6971178-2098-11e8-8cf7-74bfb2f6a992.png">
- Tested some edge cases like returning null from the ListEmptyComponent
- Tested in an app that uses FlatList + ListEmptyComponent
[GENERAL] [MINOR] [VirtualizedList] - Don't wrap ListEmptyComponent in an extra view
Closes https://github.com/facebook/react-native/pull/18206
Differential Revision: D7266274
Pulled By: sahrens
fbshipit-source-id: 4636d2418474a4c86ac63e5e18a9afc391a518c5
Summary:
Includes React Native and its dependencies Fresco, Metro, and Yoga. Excludes samples/examples/docs.
find: ^(?:( *)|( *(?:[\*~#]|::))( )? *)?Copyright (?:\(c\) )?(\d{4})\b.+Facebook[\s\S]+?BSD[\s\S]+?(?:this source tree|the same directory)\.$
replace: $1$2$3Copyright (c) $4-present, Facebook, Inc.\n$2\n$1$2$3This source code is licensed under the MIT license found in the\n$1$2$3LICENSE file in the root directory of this source tree.
Reviewed By: TheSavior, yungsters
Differential Revision: D7007050
fbshipit-source-id: 37dd6bf0ffec0923bfc99c260bb330683f35553e
Summary:
Sticky headers for inverted lists should still stick at the top of the list instead of the bottom.
Tested by adding the inverted prop to the SectionList example in RNTester.
It does add a prop to ScrollView but it's very specific to the inverted list implementation, not sure if it should be documented.
[GENERAL][ENHANCEMENT][LISTS] - Support sticky headers for inverted Lists
Closes https://github.com/facebook/react-native/pull/17762
Differential Revision: D6830784
Pulled By: sahrens
fbshipit-source-id: 6841fdd46e04b30547659d85ff54c3a21c61a8a2
Summary:
Setting `windowSize = 0` doesn't make sense. Let's make sure we catch this problem in the constructor so that it doesn't cause inexplicable list behavior.
Also fixed an invariant in `VirtualizeUtils` that is meant to prohibit non-monotonically-increasing offset arrays. As written, the invariant condition can never actually be violated.
Reviewed By: sahrens
Differential Revision: D6625302
fbshipit-source-id: b2a983cbe7bb5fbe0aed7c5d59e69a8a00672993
Summary:
In the current implementation of the `VirtualizedList` the `onViewableItemsChanged` callback wouldn't trigger if the underlying list data changes. (see example snack https://snack.expo.io/Hk5703eBb)
I added a method in the `ViewabilityHelper` to invalidate the cached viewableIndices, which gets triggered when the list-data changes.
Closes https://github.com/facebook/react-native/pull/14922
Differential Revision: D5864537
Pulled By: sahrens
fbshipit-source-id: 37f617763596244208548817d5b138dadc12c75d
Summary: FlatList only supports one viewability configuration and callback. This change extends FlatList and VirtualizedList to support multiple viewability configurations and corresponding callbacks.
Reviewed By: sahrens
Differential Revision: D5720860
fbshipit-source-id: 9d24946362fa9001d44d4980c85f7d2627e45a33
Summary:
This uses `context` to render inner lists of the same orientation to a plain `View` without
virtualization instead of rendering nested `ScrollView`s trying to scroll in the same direction,
which can cause problems.
Reviewed By: bvaughn
Differential Revision: D5174942
fbshipit-source-id: 989150294098de837b0ffb401c7f5679a3928a03
Summary:
Fixes https://github.com/facebook/react-native/issues/13784
The section footer was only rendered with the last item of the section. However, that meant in sections where no items were rendered, no section footer would be rendered. This patch makes sure that when there are no items the section footer is rendered with the section header in addition to adding tests asserting the existance of section footers in empty lists.
One potential point of contention is whether or not a section separator (as defined by the `SectionSeparatorComponent` prop to `<SectionList>`) should be rendered in an empty list. I did not include a section separator for empty lists, but let me know if you think one should be included. See the test plan below for an image of an empty section rendered without a section separator.
I was also running into a lint error, `no-alert`, in `SectionListExample.js` around line 135 that blocked me from publishing. This error looks to be triggered when the `alert()` global function is called, so to fix the error I added an import for the `Alert` module and called the `alert()` function on that module.
To help debug the `scrollToLocation()` behavior that was modified as a part of this PR I added three buttons (can be seen in the test plan image) which scroll to arbitrary points in the list.
Reviewed By: sahrens
Differential Revision: D5084095
fbshipit-source-id: 4c98bebc1c3f1ceaa5a634fa144685d83d1072df
Summary:
Hey there :)
Please let me know if the name `ListEmptyComponent` should be changed. I also thought about `ListNoItemsComponent`. Or maybe `ListPlaceholderComponent`?
- [x] Explain the **motivation** for making this change.
- [x] Provide a **test plan** demonstrating that the code is solid.
- [x] Match the **code formatting** of the rest of the codebase.
- [x] Target the `master` branch, NOT a "stable" branch.
In a FlatList, I wanted to show some placeholder when my data is empty (while keeping eventual Header/Footer/RefreshControl).
A way around this issue would be to do something like adding a `ListHeaderComponent` that checks if the list is empty, like so:
```js
ListHeaderComponent={() => (!data.length ? <Text style={styles.noDataText}>No data found</Text> : null)}
```
But I felt it was not easily readable as soon as you have an actual header.
This PR adds a `ListEmptyComponent` that is rendered when the list is empty.
I added tests for VirtualizedList, FlatList and SectionList and ran `yarn test -- -u`. I then checked that the snapshots changed like I wanted.
I also tested this against one of my project, though I had to manually add my changes because the project is on RN 0.43.
Here are the docs screenshots:
- [VirtualizedList](https://cloud.githubusercontent.com/assets/82368/25566000/0ebf2b82-2dd2-11e7-8b80-d8c505f1f2d6.png)
- [FlatList](https://cloud.githubusercontent.com/assets/82368/25566005/2842ab42-2dd2-11e7-81b4-32c74c2b4fc3.png)
- [SectionList](https://cloud.githubusercontent.com/assets/82368/25566010/368aec1e-2dd2-11e7-9425-3bb5e5803513.png)
Thanks for your work!
Closes https://github.com/facebook/react-native/pull/13718
Differential Revision: D4993711
Pulled By: sahrens
fbshipit-source-id: 055b40f709067071e40308bdf5a37cedaa223dc5
Summary:
The main reason to use **VirtualizedList** is to set the `getItem` and `getItemCount` props, so having default values for these props makes things error prone.
* In **VirtualizedList**, changed the `getItem` and `getItemCount` props from optional to required, and removed default values.
* Ensured that implementing classes **FlatList** and **SectionVirtualizedList** are always passing these props.
* Updated VirtualizedList-test.js accordingly.
Reviewed By: sahrens
Differential Revision: D4980236
fbshipit-source-id: ad1838931253bc61ff9068c40929f6e9c755b92c
Summary:
These got smashed together with some weird rebase snafu. They are pretty intertwined anyway so the value of
separate commits is minimal (e.g. separate commits would not revert cleanly anyway).
== [lists] better fill rate logging (previously D4907958)
After looking through some production data, I think this will address all the issues we're seeing. Now:
- Header/Footer getting no longer counted as blank.
- Avoid floating point for Scuba.
- Compare actual time of blankness, not just samples.
- Include both "any" vs. "mostly" blank (similar to 1 and 4 frame drops).
- Include events where there is no blankness so we have a baseline.
- Remove events with too few samples
**Test Plan: **
A bunch of scrolling in FlatListExample
T17384966
== [Lists] Update SectionSeparatorItem docs (previously D4909526)
Forgot to update the language here when we modified the behavior with the introduction of separator
highlighting support.
** Test Plan: **
nope.
== [Lists] Add renderSectionFooter prop to SectionList (previously D4923353)
Handy for things like "see more" links and such.
The logic here is to render the footer last, *after* the bottom section separator. This is to preserve
the highlighting behavior of the section separator by keeping it adjacent to the items.
**Test Plan: **
Added to snapshot test and example:
{F66635525}
{F66635526}
== [SectionList] Add a bunch more info for rendering items and separators (previously D4923663)
This extra info can be helpful for rending more complex patterns.
**Test Plan: **
Made snapshot test more comprehensive and inspected the output.
== [Lists] reduce render churn (previously D4924639)
I don't think the velocity based leadFactor is helping and might actually be hurting because
it causes a lot of churn in the items we render.
Instead, this diff introduces fillPreference which biases the window expansion in the direction of scroll,
but doesn't actually affect the final bounds of the window at all, so items that are already rendered are
more likely to stay rendered.
**Test Plan: **
Played around in debug mode and watched the overlay - seems better. Also tests all pass.
T16621861
== [Lists] Add initialScrollIndex prop
Makes it easy to load a VirtualizedList at a location in the middle of the content without
wasting time rendering initial rows that aren't relevant, for example when opening an infinite calendar
view to "today".
**Test Plan: **
With debug overlay, set `initialScrollIndex={52}` prop in `FlatListExample` and
and see it immediately render a full screen of items with item 52 aligned at the top of the screen. Note
no initial items are mounted per debug overlay. Scroll around a bunch and everything else seems to work
as normal.
No SectionList impl since `getItemLayout` isn't easy to use there.
T17091314
Reviewed By: bvaughn
Differential Revision: D4907958
fbshipit-source-id: 8b9f1f542f9b240f1e317f3fd7e31c9376e8670e
Summary:
**Bug Description**
The FlatList component receives content items via the data prop, and renders an initial number of items on the app's view. When a user scrolls to the end of the list, the component will append and render more available items at the end of the list. There was a bug where when the content was filtered, there were more available items but the component did not append/render them. This is due to the current appending/rendering logic in VirtualizedList, which does not account for data changes as a condition for updating/rendering. VirtualizedList is a dependency of FlatList, so this issue affects FlatList as well.
**Approach to Fixing Bug**
(i) Reproduce bug on iOS view of FlatList.
(ii) For VirtualizedList component:
# Isolate onEndReached function that appends more data to component UI.
# Isolate _onContentSizeChange function that is called when list content changes.
# Write snapshot tests using jest, based off existing test for FlatList.
# Refactor logic to append more data to list into _maybeCallOnEndReached function.
# Call _maybeCallOnEndReached in both _onContentSizeChange and _onScroll.
(iii) Run snapshot tests and observe jest output.
(iv) Bring up iOS view of FlatList and check that component now renders more items when content is filtered.
Many thanks to sahrens for guidance in developing this code!
Reviewed By: sahrens
Differential Revision: D4877388
fbshipit-source-id: c10c9eef1912f491450a62b81a9bc41f7f784203
Summary:
It's just causing problems (e.g. when combined with transform animations like those used
in some navigators) and hopefully it's not necessary with JS-side windowing. If people need the
perf, they can turn it on themselves.
Should fix https://github.com/facebook/react-native/issues/13316 and related issues.
Reviewed By: achen1
Differential Revision: D4884147
fbshipit-source-id: 95c82448581076c0d0b2c80b1cd80cc294898174
Summary:
A nice bit of polish for apps is to update the separators between list items
when press actives the highlight (things get especially noticeable/ugly when
the separators are not full width and don't adjust). This can be difficult to
coordinate and update efficiently, so we bake the functionality into
`VirtualizedList`.
The approach taken here is a little different from `ListView`. We pass a new
`separators` object with `renderItem` that has easy-to-use callbacks for toggling
the 'highlighted' prop on both adjacent separators - they can be wired up
directly to the `onShow/HideUnderlay` props of `TouchableHighlight` (pit of
success and all that - we want those RN apps to be polished!), but we also
provide a more generic `separators.updateProps` method to set any custom
props. This also passes in `leadingItem` so more custom wiring can be done on
initial render (e.g. linking the highlight state with `Animated`).
This also moves the separator rendering into the `CellRenderer`. I think this might
also fix some subtle measurement bugs with the `onLayout` not capturing the
height of the separator, so that's nice too, but the main reason is to have
an easy place to store the state so we don't have to re-render the entire list
like `ListView` does. Instead we track references to the cells and call update
only on the two we care about so the feedback is instantaneous even with big,
heavy lists.
This diff also messes with a bunch of flow and updates the example to be more
like a standard list.
`SectionList` support is coming in a stacked diff.
**TestPlan**
Video demo:
https://youtu.be/uFE7qGA0mg4
Pretty sure this is backwards compatible....
Reviewed By: thechefchen
Differential Revision: D4833557
fbshipit-source-id: 685af46243ba13246bf280dae8a4223381ce8cea
Summary:
If tracking is enabled and the sampling check passes on a scroll or layout event,
we compare the scroll offset to the layout of the rendered items. If the items don't cover
the visible area of the list, we fire an `onFillRateExceeded` call with relevant stats for
logging the event through an analytics pipeline.
The measurement methodology is a little jank because everything is async, but it seems directionally
useful for getting ballpark numbers, catching regressions, and tracking improvements.
Benchmark testing shows a ~2014 MotoX starts hitting the fill rate limit at about 2500 px / sec,
which is pretty fast scrolling.
This also reworks our frame rate stuff so we can use a shared `SceneTracking` thing and track blankness
globally.
Reviewed By: bvaughn
Differential Revision: D4806867
fbshipit-source-id: 119bf177463c8c3aa51fa13d1a9d03b1a96042aa