Code Monkey home page Code Monkey logo

recyclerlistview's Introduction

RecyclerListView

npm version appveyor License

If this project has helped you out, please support us with a star ๐ŸŒŸ.

This is a high performance listview for React Native and Web with support for complex layouts. JS only with no native dependencies, inspired by both RecyclerView on Android and UICollectionView on iOS.

npm install --save recyclerlistview

For latest beta:
npm install --save recyclerlistview@beta

Note: Documentation will be upgraded soon, for now check code comments for clarity and exploring features. This component is actively tested with React Native Web as well.

Overview and features

RecyclerListView uses "cell recycling" to reuse views that are no longer visible to render items instead of creating new view objects. Creation of objects is very expensive and comes with a memory overhead which means as you scroll through the list the memory footprint keeps going up. Releasing invisible items off memory is another technique but that leads to creation of even more objects and lot of garbage collections. Recycling is the best way to render infinite lists that does not compromise performance or memory efficiency.

Apart from all performance benefits RecyclerListView comes with great features out of the box:

  • Cross Platform, works on Web
  • Supports staggered grid layouts
  • Supports variable height items even if dimensions cannot be predetermined (prop - forceNonDeterministicRendering)
  • Instant layout switching like going from GridView to ListView and vice versa
  • End reach detections
  • Horizontal Mode
  • Viewability Events
  • Initial render offset/index support
  • Footer support
  • Reflow support on container size change with first visible item preservation
  • Scroll position preservation
  • Window scrolling support for web
  • (New) ItemAnimator interface added, customize to your will how RLV handles layout changes. Allows you to modify animations that move cells. You can do things like smoothly move an item to a new position when height of one of the cells has changed.
  • (New) Stable Id support, ability to associate a stable id with an item. Will enable beautiful add/remove animations and optimize re-renders when DataProvider is updated.
  • (New) Sticky recycler items that stick to either the top or bottom.

Why?

RecyclerListView was built with performance in mind which means no blanks while quick scrolls or frame drops. RecyclerListView encourages you to have deterministic heights for items you need to render. This does not mean that you need to have all items of same height and stuff, all you need is a way to look at the data and compute height upfront so that RecyclerListView can compute layout in one pass rather than waiting for the draw to happen. You can still do all sorts of GridViews and ListViews with different types of items which are all recycled in optimal ways. Type based recycling is very easy to do and comes out of the box.

In case you cannot determine heights of items in advance just set forceNonDeterministicRendering prop to true on RecyclerListView. Now, it will treat given dimensions as estimates and let items resize. Try to give good estimates to improve experience.

Demo

Production Flipkart Grocery Demo Video (or try the app): https://youtu.be/6YqEqP3MmoU
Infinite Loading/View Change (Expo): https://snack.expo.io/@naqvitalha/rlv-demo
Mixed ViewTypes: https://snack.expo.io/B1GYad52b
extendedState,stableIDs and ItemAnimator (Expo): https://snack.expo.io/@arunreddy10/19bb8e
Sample project: https://github.com/naqvitalha/travelMate
Web Sample (Using RNW): https://codesandbox.io/s/k54j2zx977, https://jolly-engelbart-8ff0d0.netlify.com/
Context Preservation Sample: https://github.com/naqvitalha/recyclerlistview-context-preservation-demo

Other Video: https://www.youtube.com/watch?v=Tnv4HMmPgMc

Watch Video

Props

Prop Required Params Type Description
layoutProvider Yes BaseLayoutProvider Constructor function that defines the layout (height / width) of each element
dataProvider Yes DataProvider Constructor function the defines the data for each element
contextProvider No ContextProvider Used to maintain scroll position in case view gets destroyed, which often happens with back navigation
rowRenderer Yes (type: string | number, data: any, index: number) => JSX.Element | JSX.Element[] | null Method that returns react component to be rendered. You get the type, data, index and extendedState of the view in the callback
initialOffset No number Initial offset you want to start rendering from; This is very useful if you want to maintain scroll context across pages.
renderAheadOffset No number specify how many pixels in advance you want views to be rendered. Increasing this value can help reduce blanks (if any). However, keeping this as low as possible should be the intent. Higher values also increase re-render compute
isHorizontal No boolean If true, the list will operate horizontally rather than vertically
onScroll No rawEvent: ScrollEvent, offsetX: number, offsetY: number) => void On scroll callback function that executes as a user scrolls
onRecreate No (params: OnRecreateParams) => void callback function that gets executed when recreating the recycler view from context provider
externalScrollView No { new (props: ScrollViewDefaultProps): BaseScrollView } Use this to pass your on implementation of BaseScrollView
onEndReached No () => void Callback function executed when the end of the view is hit (minus onEndThreshold if defined)
onEndReachedThreshold No number Specify how many pixels in advance for the onEndReached callback
onEndReachedThresholdRelative No number Specify how far from the end (in units of visible length of the list) the bottom edge of the list must be from the end of the content to trigger the onEndReached callback
onVisibleIndicesChanged No TOnItemStatusChanged Provides visible index; helpful in sending impression events
onVisibleIndexesChanged No TOnItemStatusChanged (Deprecated in 2.0 beta) Provides visible index; helpful in sending impression events
renderFooter No () => JSX.Element | JSX.Element[] | null Provide this method if you want to render a footer. Helpful in showing a loader while doing incremental loads
initialRenderIndex No number Specify the initial item index you want rendering to start from. Preferred over initialOffset if both specified
scrollThrottle No number iOS only; Scroll throttle duration
canChangeSize No boolean Specify if size can change
distanceFromWindow No number (Depricated) Use applyWindowCorrection() API with windowShift. Usage?
applyWindowCorrection No (offset: number, windowCorrection: WindowCorrection) => void (Enhancement/replacement to distanceFromWindow API) Allows updation of the visible windowBounds to based on correctional values passed. User can specify windowShift; in case entire RecyclerListWindow needs to shift down/up, startCorrection; in case when top window bound needs to be shifted for e.x. top window bound to be shifted down is a content overlapping the top edge of RecyclerListView, endCorrection: to alter bottom window bound for a similar use-case. Usage?
useWindowScroll No boolean Web only; Layout Elements in window instead of a scrollable div
disableRecycling No boolean Turns off recycling
forceNonDeterministicRendering No boolean Default is false; if enabled dimensions provided in layout provider will not be strictly enforced. Use this if item dimensions cannot be accurately determined
extendedState No object In some cases the data passed at row level may not contain all the info that the item depends upon, you can keep all other info outside and pass it down via this prop. Changing this object will cause everything to re-render. Make sure you don't change it often to ensure performance. Re-renders are heavy.
itemAnimator No ItemAnimator Enables animating RecyclerListView item cells (shift, add, remove, etc)
style No object To pass down style to inner ScrollView
scrollViewProps No object For all props that need to be proxied to inner/external scrollview. Put them in an object and they'll be spread and passed down.
layoutSize No Dimension Will prevent the initial empty render required to compute the size of the listview and use these dimensions to render list items in the first render itself. This is useful for cases such as server side rendering. The prop canChangeSize has to be set to true if the size can be changed after rendering. Note that this is not the scroll view size and is used solely for layouting.
onItemLayout No number A callback function that is executed when an item of the recyclerListView (at an index) has been layout. This can also be used as a proxy to itemsRendered kind of callbacks.
windowCorrectionConfig No object Used to specify is window correction config and whether it should be applied to some scroll events

For full feature set have a look at prop definitions of RecyclerListView (bottom of the file). All ScrollView features like RefreshControl also work out of the box.

applyWindowCorrection usage

applyWindowCorrection is used to alter the visible window bounds of the RecyclerListView dynamically. The windowCorrection of RecyclerListView along with the current scroll offset are exposed to the user. The windowCorrection object consists of 3 numeric values:

  • windowShift - Direct replacement of distanceFromWindow parameter. Window shift is the offset value by which the RecyclerListView as a whole is displaced within the StickyContainer, use this param to specify how far away the first list item is from window top. This value corrects the scroll offsets for StickyObjects as well as RecyclerListView.
  • startCorrection - startCorrection is used to specify the shift in the top visible window bound, with which user can receive the correct Sticky header instance even when an external factor like CoordinatorLayout toolbar.
  • endCorrection - endCorrection is used to specify the shift in the bottom visible window bound, with which user can receive correct Sticky Footer instance when an external factor like bottom app bar is changing the visible view bound.

As seen in the example below

Alt Text

Typescript

Typescript works out of the box. The only execption is with the inherited Scrollview props. In order for Typescript to work with inherited Scrollview props, you must place said inherited Scrollview props within the scrollViewProps prop.

<RecyclerListView
  rowRenderer={this.rowRenderer}
  dataProvider={queue}
  layoutProvider={this.layoutProvider}
  onScroll={this.checkRefetch}
  renderFooter={this.renderFooter}
  scrollViewProps={{
    refreshControl: (
      <RefreshControl
        refreshing={loading}
        onRefresh={async () => {
          this.setState({ loading: true });
          analytics.logEvent('Event_Stagg_pull_to_refresh');
          await refetchQueue();
          this.setState({ loading: false });
        }}
      />
    )
  }}
/>

Guides

  • Sample Code
  • Performance
  • Sticky Guide
  • Web Support: Works with React Native Web out of the box. For use with ReactJS start importing from recyclerlistview/web e.g., import { RecyclerListView } from "recyclerlistview/web". Use aliases if you want to preserve import path. Only platform specific code is part of the build so, no unnecessary code will ship with your app.
  • Polyfills Needed: requestAnimationFrame, ResizeObserver

License

Apache v2.0

Contact Us

Please open issues for any bugs that you encounter. You can reach out to me on twitter @naqvitalha or, write to [email protected] for any questions that you might have.

recyclerlistview's People

Contributors

abhishek-18 avatar adnaan1703 avatar ae0011 avatar ananyachandra14 avatar anirudhagarwal365 avatar arunreddy10 avatar bobychaudhary avatar cmcaboy avatar dylan0916 avatar elviraburchik avatar fortmarek avatar hirbod avatar inayat1 avatar isle-prashant avatar jayfkipl avatar kevin-kp avatar marnusw avatar muskeinsingh avatar naqvitalha avatar nimishsinghal avatar radeno avatar rajatgupta26 avatar surya-kanoria avatar swapnil1104 avatar tafelito avatar wojtus7 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

recyclerlistview's Issues

Portrait/Landscape rotation - resize issue

When I rotate the device the cells are upgraded their size only when I scroll, and not on rotation. I've set the canChangeSize={true} props, the _layoutProvider is called once the device is rotated with the right new sizes, but the cell width is expanded or reduced only after some scrolling.

onEndReached called when initializing list

Is there any reason why the _processOnEndReached is being called here? https://github.com/Flipkart/ReactEssentials/blob/78203c98ad1caf6ec379687dc3842d29b77f4148/src/core/RecyclerListView.js#L258

The onEndReached callback is always called before loading the first items, so if I wanna add some logic to add more items when reaching the end, like an infinite loading, it will be called even if it's not needed.

Is there any other reason to do that? Or maybe it could check if the dataProvided is not empty?

UPDATE: This only happens if forceNonDeterministicRendering = true

Rendering same rows repeatedly on ios

ReactEssentials is exactly what I need. But I faced with this interesting situation when I tested with real data. I have a long list. But all list rendering with the same items (first 13 item).

Working fine on android but I stuck on ios.

recyclerlistview: ^1.1.4
react-native: 0.49.3

class UserList extends Component {
    constructor(props){
        super(props);
        
        let dataProvider = new DataProvider((r1, r2) => {
            return r1 !== r2;
        });

        let { width } = Dimensions.get("window");

        this._layoutProvider = new LayoutProvider(
            index => {
                return ''
            },
            (type, dim) => {
                dim.width = width;
                dim.height = 84;
            }
        );

        this.renderRow = this.renderRow.bind(this);

        this.state = {
            dataProvider: dataProvider.cloneWithRows(props.rows)
        };
    }

    componentWillReceiveProps(nextProps){
        let dataProvider = new DataProvider((r1, r2) => {
            return r1 !== r2;
        });

        this.setState({ dataProvider: dataProvider.cloneWithRows(nextProps.rows)});
    }

    renderRow(type, { node }) {
        return (
            <UserRow user={ node } selectedAccount={this.props.selectedAccount} />
        );
    }

    render(){
        const { listKey } = this.props;
        return (
            <Content>
                <RecyclerListView key={listKey} style={{width: 400, height: 400 }} layoutProvider={this._layoutProvider} dataProvider={this.state.dataProvider} rowRenderer={this.renderRow} />
            </Content>
        )
    }
}

export default UserList;

Question: How to update initialRenderIndex when changing rows

I'm trying to update the rows with cloneWithRows, but looks like updating initialRenderIndex at the same time as updating the dataProvider doesn't actually work. Maybe that's the way it was intended to work, but I also noticed that the recyclerlistview maintains scrollposition even if the overall height of it changes.

I made a quick snack of this case here: https://snack.expo.io/SJyh3xiyG

You can see that I have an initialRenderIndex of 20, and there are 100 rows in total. Upon changing the rows to be 10, the scroll position hasn't changed and you'd have to scroll the recyclerlistview a little bit and then the scroll position is fixed.

Changing the initialRenderIndex doesn't have an effect as well, as I mentioned before.

Sticky Headers with an External ScrollView

I've been experimenting with the new externalScrollView prop trying to achieve a true sticky header experience. And this is what I came up with so far.

sticky-header-demo

My solution was replacing the normal ScrollView with an Animated.ScrollView and have its onScroll feed into an Animated value that I then use in the rowRenderer to stick some rows to the top.

This is my custom scrollview component.

class AnimatedScrollView extends React.Component {
  render() {
    return (
      <Animated.ScrollView
        ref={ref => (this._scrollView = ref)}
        scrollEventThrottle={1}
        {...this.props}
        onScroll={Animated.event(
          [{ nativeEvent: { contentOffset: { y:animatedScrollViewOffsetY } } }],
          {
            useNativeDriver: true,
            listener: this.props.onScroll
          }
        )}
      />
    );
  }
}

I then use the animatedScrollViewOffsetY Animated Value in the rowRenderer and I calculate when the views should start sticking to the top like that:

const stickyConfiguration = {
  startAt: 0,
  duration: -1 * HEADER_HEIGHT
};
_.forEach(this.state.dataProvider._data, (row, rowIndex) => {
  if (rowIndex < index) {
    stickyConfiguration.startAt += this.getRowHeight(row.viewType);
  } else {
    if (rowIndex > index && row.viewType === ViewTypes.DAY_HEADER) {
      return false;
    } else {
      stickyConfiguration.duration += this.getRowHeight(row.viewType);
    }
  }
});

I then pass the y:animatedScrollViewOffsetY to my component which positions itself with some transforms:

const translateY = {
  transform: [
    {
      translateY: this.props.animatedScrollViewOffsetY.interpolate({
        inputRange: [
          0,
          stickyConfiguration.startAt,
          stickyConfiguration.startAt + stickyConfiguration.duration
        ],
        outputRange: [0, 0, stickyConfiguration.duration],
        extrapolate: 'clamp'
      })
    }
  ]
};

One of the challenges I faced was with zIndex values. I fixed it for iOS by changing the code for ViewRenderer, but couldn't fix it on Android. There's also the problem with the onScroll event that has to run both the Animated.Event and do recyclerlistview's logic as well. I couldn't get around that myself.

I unfortunately can't just fork recyclerlistview and implement my solution since it doesn't work for Android yet, but that at least shows that the feature can be implemented. I'm thinking an additional property stickyViewTypes or something like that.

Please let me know if you need more clarification on how I made that demo work. Would love to have this added to recyclerlistview soon! ๐Ÿ‘

Opacity = 0 VS Display = none

Relative to #71

A simple example, lets say we have a view that looks like this:
Image + Text

And the Text is optional, while recycling if your component renders Text on the basis of whether text is there or not the Text component will see multiple unmounts/mounts. This might lead to drop in performance. A better way would be to simply hide Text (opacity = 0) and let it be there since it might get reused in future.

I want to know is there any difference between Opacity = 0 and Display = none for hiding objects in recycle view

Is object with Display = none recyclable? I turn on show layout bounds and Display = none has no bounds but Opacity = 0 has , So Is Display = none has inconvenient unmounts/mounts

view recycling and "prepare for reuse"

On iOs and android we use "prepare for reuse" to make sure a view is ready to be reused.
The simplest example is Image if there were an image already loaded and you set a new image that wont load (network error or such), you end with a view with the image for another cell.

Is there any way in your lib to set the image to "null" before it is reused?

Thanks

Question : measure hight of text

I have a large data set contains different media and text

I can calculate all dimensions before rendering . except text

How can I exactly calculate text height for known width?? (I need a solution that works for web too)
Is the height depends on font-family too? Or just font-size?

Feedback on RecyclerListView

Hi, following up on some conversations with @naqvitalha over in the react-native-web repo. Here are some findings/comparisons to our scroller from @madnl, who tried the component in Twitter Lite's timelines (on desktop Chrome):

  • Proximity events
    • only support for 'bottom reached' event (no distinction between near and at)
    • no at top, near top events
  • new items injected at top leads to loss of scroll position
  • after items injected at top - scrolling upwards leads to constant scroll jumps (even in Desktop Chrome, which is the most forgiving of browsers for scroll adjustments)
  • strange layout issues where items appeared offsetted to the left

  • unsure how virtualization is happening - all items seem to be rendered at once (coming back to a timeline has noticeable lag)

  • frequent stack overflows

  • A mechanism for saving position when coming back to timeline exists, but not sure how it is applied or if it works (see ContextProvider).

  • Sometimes items overlap

Although the following are not blocking issues since our current scroller does not have them either, it should be stated that this library does not seem to provide support for:

  • reverse-order lists
  • tombstones or entry previews to support fast scrolling without the rendering overhead.

For the most part, it could work, although there is a point where it might not be generally usable for our timelines - given that timelines change in a non-linear way, there does not seem to be an anchoring mechanism that ensures the most visible item stays put when new items are rendered or removed above it. This would require identifying the items by key, instead of by index how it is now.

when set forceNonDeterministicRendering={true}, mistake in performance occurred :(

when set forceNonDeterministicRendering={true}, mistake in performance occurred :(, but i cannot set it to false; because layout will be damaged, any one can help??

this without forceNonDeterministicRendering but performance is high.
43d6a89a-1569-47de-a33f-3f81d01c0055.
and this with forceNonDeterministicRendering, layout is awesome but performance is poor
85dce042-553f-4ffe-b498-7ffc31c88345

any idea ??

Cannot read property 'getLayoutDimension' of undefined

If I initially load a page before having data, returning an empty page(null/No Data) then fetch data from server after component mounted and set the data for data provider to my new data this error is produced at VirtualRenderer.getLayoutDimension.

On IOS it imediatly displays the "'getLayoutDimension' of undefined" error while on android the red screen displays 'Node has not been attached to a view' and the getLayoutDimension goes as a warning in background and on Debug console.

Commenting out the onEndReached property makes the problem stop.

I have tried to reproduce the error on snack/expo, but it does not reproduce the same error. On snack/expo it sometimes just work and other times expo just crashes.

Link to example: https://snack.expo.io/ryy4QxFRZ

Prebuild Distributed Files

Currently the library seems to export the source files as they are, without transpiling ES6 or JSX syntax down to more vanilla JS. This forces users of the library to match the assumed babel configuration this library expects.

Cannot scroll if nested inside ScrollView

Hi,
I'm facing a problem that RecyclerListView cannot scroll if it's nested inside a ScrollView. It happens in Android, I haven't tested with iOs yet.
Do you have any idea about this problem?

Best regards,
Nghia.

Force rerendering when data changes

I have a case where some data in my Redux store is being updated, and I want the RecyclerListView to update its rows. Currently, if the row has been rendered it's not updated until I scroll far away and then scroll back. Is there a method that I can call to imperatively rerender the visible rows?

JavaScript with staggered grid support.

You mentioned in document that "We built RecyclerListView which is a high performance list view written purely in JavaScript with staggered grid support."

Please provide instruction, How can I achieve staggered RecyclerListView .

Available Methods for navigating the list

There is no documentation on what available props and methods.
Is there any method for navigating the list like scrollTo, scrollToIndex, scrollToItem
or a prop for setting initial list item to be focused?

undefined is not an object (evaluating 'itemRect.y')

This happens when I first run the app on my device:

image uploaded from ios 9

This is my component:

class EventList extends Component {
  render() {
    const { events, starredIds, starFn, unstarFn } = this.props;
    let { width } = Dimensions.get("window");

    let eventsAndStars = events.map(event => {
      return { ...event, starred: _.includes(starredIds, event.id) };
    });

    let dataProvider = new DataProvider((r1, r2) => {
      return r1 !== r2;
    });

    return h(RecyclerListView, {
      dataProvider: dataProvider.cloneWithRows(eventsAndStars),
      ref: "list",
      onContentSizeChange: () => {
        try {
          this.refs.list.scrollToIndex(0);
        } catch (e) {
          console.log("scrolling to top went wrong: ", e);
        }
      },
      style: styles.container,
      layoutProvider: new LayoutProvider(
        index => 0,
        (type, dim) => {
          dim.width = width;
          dim.height = 90;
        }
      ),
      showsVerticalScrollIndicator: false,
      rowRenderer: (type, event) => {
        const {
          id,
          featured,
          name,
          description,
          url,
          startDate,
          endDate
        } = event;
        const starred = _.includes(starredIds, event.id);
        const now = new Date();
        return h(EventRow, {
          id,
          name,
          description,
          url,
          startDate,
          endDate,
          starred,
          starFn,
          unstarFn,
          featured,
          now
        });
      }
    });
  }
}

I'm using RN 0.47.2

Invalid semver version for latest update

Hi!

The latest version has been released as version 1.0.7, the version before this was 1.0.61.

If your module is now installed via npm i --save, 1.0.61 is downloaded instead of 1.0.7. A quick fix would be to publish either a version above 1.0.61 or directly go for 1.1.0

Calling 'scrollToIndex' while manually scrolling causes blank content

I have a specific case here where there's a button that scrolls to a specific index in the list. If I tap the button when the list is idle, it scrolls there and renders things just fine, but if the user is already scrolling in the list, it scrolls to its destination and shows blank content until I start scrolling again.

As far as I understood from the source code, there's a render stack that's prepared and it's being updated on scroll. The problem is that as the user is scrolling, if I force the list to go to a specific index with no animation, the renderStack loses track of the items it should render, until I start scrolling again, and then the renderStack gets updated and it renders things correctly again.

I hope my explanation made sense. Please let me know if I need to elaborate further.

Some callback needed

@naqvitalha I want to implement a simple version of sticky header for my use case
How can I detect that which item is topmost (or bottommost) and which is coming in view report and which is go out?

RefreshControl Support

From the documents, it looks like there is no RefreshControl support yet. Do you consider this lib as a drop in replacement of FlatList in the future?
Thanks.

Rerendering row causes list to jump / snap unexpectedly

I have a list of Events that users can star. However, whenever I star that event (and therefore add the event ID to starredIds), the list snaps to the row nearest to the top. Is there a way to prevent this? It feels like bad UX.

class MyList extends Component {
  render() {
    const { events, starredIds, starFn, unstarFn } = this.props;
    let { width } = Dimensions.get("window");

    let eventsAndStars = events.map(event => {
      return { ...event, starred: _.includes(starredIds, event.id) };
    });

    let dataProvider = new DataProvider((r1, r2) => {
      return r1 !== r2;
    });

    return h(RecyclerListView, {
      dataProvider: dataProvider.cloneWithRows(eventsAndStars),
      ref: "list",
      oncontentsizechange: () => {
        try {
          this.refs.list.scrolltoindex(0);
        } catch (e) {
          console.log("scrolling to top went wrong: ", e);
        }
      },
      style: styles.container,
      layoutProvider: new LayoutProvider(
        index => 0,
        (type, dim) => {
          dim.width = width;
          dim.height = 90;
        }
      ),
      showsVerticalScrollIndicator: false,
      rowRenderer: (type, event) => {
        const {
          id,
          name,
          description,
        } = event;
        const starred = _.includes(starredIds, event.id);
        const now = new Date();
        return h(MyRow, {
          id,
          name,
          description,
        });
      }
    });
  }
}

Redux issue

I have an issue as same as #60 but in both android and iOS (I think the problem is not depends on OS)

My rowRenderer return an element connected to redux and I need to use redux , and I put dataProvider in the mapStateToProps

Can you please provide an example that show how we can use this library with redux?

Cannot read property 'reLayoutFromIndex' of undefined

I'm trying to change the content of the recylcerlistview, but I keep getting Cannot read property 'reLayoutFromIndex' of undefined. What could be causing that error?

I'm updating my data in the following way:

this.setState(prevState => ({
   dataProvider: prevState.dataProvider.cloneWithRows(newRows)
}));

The error happens in RecyclerListView.js:224 in the line
this._virtualRenderer.getLayoutManager().reLayoutFromIndex(newProps.dataProvider._firstIndexToProcess, newProps.dataProvider.getSize());

That was called from componentWillReceiveProps of RecyclerListView in the line this._checkAndChangeLayouts(newProps);

_virtualRenderer is getting set to null for some reason. Could you please explain what could be causing that problem

Blank area

I have a list with about 100 items . when I scroll I see blank area for 0.5 second

I try your sample with last version of react native

It has not same performance like your YouTube and I see blank area . I test at release mode in android 7 phone with 8 core CPU and 8 gig ram

Also in your sample except image all data is same and not changed so we have no cha he in view except images . If you try with better data and each row has different price and ... , the performance decreases and we have more blank area

I also increase renderAheadOffset to 320 and 640 but still see blank area even in your sample project

LayoutProvider and item

I have an use case that LayoutProvider must pass me item to calculate dim.width and dim.height

like the following code

 this._layoutProvider = new LayoutProvider(
            index => {
                if (index % 3 === 0) {
                    return ViewTypes.FULL;
                } else if (index % 3 === 1) {
                    return ViewTypes.HALF_LEFT;
                } else {
                    return ViewTypes.HALF_RIGHT;
                }
            },
            (type, dim , item) => {
                  dim.width = item.width();
                  dim.height = item.height();
            }
        );

(type, dim , item) => {} OR (type, dim , index) => {} is good

Maintain scroll position when adding rows to the top of the list

When I call dataProvider.cloneWithRows() and add more rows to the top of the list. The scroll position is lost. I tried investigating by reading the source code. I'd appreciate it if you could help with this!

And thanks for the great library! Its performance is amazing.

onVisibleIndexesChanged returns wrong values when initialRenderIndex is provided

I've been trying to utilize both the onVisibleIndexesChanged and initialRenderIndex props at the same time, but I'm facing a weird behaviour that I'm not sure if it's intended to be that way.

When I provide an initialRenderIndex value of 10, onVisibleIndexesChanged is fired first with the values [0, 1, 2, 3, ...] and then it's fired again with the correct values [9, 10, 11, 12, 13, ...]

I've reproduced in this snack https://snack.expo.io/ByBPIAtyM

Has it been implemented that way on purpose? And if so, what workaround would you guys suggest?

change size of rendered item

Good day based on the source code I can see that there is an onSizeChange(), but I cannot find anything on how to change the size in such a mater that this event is triggered. Any pointers on what too look for?

ListView starts rendering at index 1

This is almost certainly not a bug in the RecyclerListView code (but might use a clarification in the documentation).

When I render my list, the first visible item in my list is at index 1 in my data provider. When I overscroll to the top (like a pull to refresh gesture), I can see my index 0 item being rendered in that position (off the top of the window). Am I missing styling?

[ReactNative] this.virtualRenderer not always initialized in RecyclerListView

First of all, thanks a lot for creating this great list view component. The built in FlatList and SectionList components of react-native are pretty bad at handling initial scrollOffsets, where this component really shines (especially with ContextProvider).

I found a bug where new props lead to exceptions through the componentWillReceiveProps call in RecyclerListView:

When the RecyclerListViews parent is re-rendered early after being mounted, the RecyclerListView's componentWillReceiveProps is called, but this.virtualizedRenderer is not yet initialized. This will lead to two exceptions in the following lines:

As a quick fix, I wrapped both lines in an if (this.virtualRenderer) { ... } and there are no more exceptions or weird behavior.

You can try out the following sample to reproduce the bug:

Sample Repo

Sticky header

How can I have a sticky header like the following gif
sticky header

Blank white when scrolling

when I scroll slowly it looks normal. But if I scroll quickly then the white screen appears but when the scroll stops displaying the item immediately.
It makes the users less comfortable. Is there any suggestion for this?

Question : Complex layout

I have a list with 10 different layout type , each type can text comment or not , For example I have an Image layout that can contain text or not , layout here is similar to blog post

Another type is Video that may contain text or not

Must I define 20 different ViewTypes for LayoutProvider ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.