GithubHelp home page GithubHelp logo

sghiassy / react-native-sglistview Goto Github PK

View Code? Open in Web Editor NEW
742.0 24.0 73.0 31.87 MB

SGListView is a memory minded implementation of React Native's ListView

License: MIT License

JavaScript 98.98% Shell 1.02%
react react-native react-native-component listview sglistview sglistview-performance sg

react-native-sglistview's Introduction

React Native SGListView

SGListView is a memory minded implementation of the React Native's ListView.

Maintainers Wanted

I'm currently looking for maintainers to help maintain and improve this package for the React-Native community. For more information please see GitHub Issue #48.

The Problem

The React Native team has done a tremendous job building a robust platform. One oversight, is the memory performance of their ListView implementation. When scrolling down long lists, the memory footprint increases linearly and will eventually exhaust all available memory. On a device as memory-constrained as a mobile device, this behavior can be a deal breaker for many.

Native ListView Performance An example of ListView performance for long lists.

The Solution

SGListView resolves React Native's ListView memory problem by controlling what's being drawn to the screen and what's kept in memory. When cells are scrolled off screen, SGListView intelligently flushes their internal view and only retains the cell's rendered bounding box - resulting in huge memory gains.

SGListView Performance An example of SGListView performance for long lists.

Installation

Install via yarn of npm

#yarn
yarn add react-native-sglistview

#npm
npm install react-native-sglistview --save

Usage

SGListView was designed to be a developer-friendly drop-in replacement for ListView. Simply import the package and change the ListView references in the render methods to SGListView. Nothing else. No fuss, no muss.

Import

Import SGListView

import SGListView from 'react-native-sglistview';

Rename

Change references from ListView to SGListView.

From:

<ListView ... />

To:

<SGListView ... />

Done

That's it. If you had a working list view and did the above two steps everything should work. If you're instead creating a ListView from scratch, then you'll need to do all the regular setup that the default ListView requires (i.e: Create and link up your datasource const dataSource = new ListView.DataSource(...)).

Simple Example

import React from 'react';
import { ListView } from 'react-native';
import SGListView from 'react-native-sglistview';

const LIST_VIEW = 'listview';

class CardListView extends React.Component {
  static renderRow(rowData, sectionID, rowID) {
    return (
      <View>
        <Text>{rowData.title}</Text>
      </View>
    );
  }

  render() {
    return (
      <SGListView
        ref={LIST_VIEW}
        dataSource={this.getDataSource()}
        renderRow={this.renderRow}
      />
    );
  }

  getDataSource() {
    const dataSource = new ListView.DataSource(
      { rowHasChanged: (r1, r2) => r1.uuid !== r2.uuid });

    const deals = this.props.deals.length > 0;
    return deals ? dataSource.cloneWithRows(this.props.deals) : dataSource;
  }
}

Working App Example

To view a fully working app example, check out the example app at: https://github.com/sghiassy/react-native-sglistview-example

Reference Configuration

SGListView passes its props to React-Native's ListView. If ListView requires a prop, then you must supply that prop to SGListView so it can pass it down. For more information read these two RN official documents: ListView component ListView performance optimize

SGListView Component

  <SGListView
    dataSource={this.getDataSource() } //data source
    ref={'listview'}
    initialListSize={1}
    stickyHeaderIndices={[]}
    onEndReachedThreshold={1}
    scrollRenderAheadDistance={1}
    pageSize={1}
    renderRow={(item) =>
      <ListItem>
        <Text>{item}</Text>
      </ListItem>
    }
  />

Configuration

SGListView provides a couple methods and options in addition to React-Native's ListView component. They are detailed here:

Methods

  • getNativeListView: Sometime you want to be able to interact with SGListView's underlying ListView instance. You can get a reference to the underlying ListView element from SGListView by calling this method.

Options

  • premptiveLoading (type: integer): SGListView will dump the internal view of each cell as it goes off the screen. Conversely, when the cell comes back on the screen, we repopulate the cell with its view. If this transition happens too late in the process, the user will see a flash on screen as the cell transitions from a blank bounding box to its full view representation. SGListView prevents this from happening by preemptively loading cells before they come on screen. By default, we load 2 cells in the future before they come on screen. SGListView allows you to override the number of cells to load preemptively through the prop premptiveLoading. Note: Because of this logic, its advised not to use ListView's prop scrollRenderAheadDistance as they can be in conflict with one another.

FAQ

Does this approach reuse cells?

Unfortunately no. Instead what SGListView does is to dump the internal view of cells as they scroll off screen, so that only a simple bounding box of the cell remains in memory.

Why do you keep cells around when they go off screen? Why don't you just remove them?

We keep cells around because we wanted SGListView to be a high-fidelity drop-in replacement for ListView - which meant sacrificing performance for compatibility.

We wanted pixel perfection between ListView and SGListView. This meant that we had to rely on ListView's underlying CSS engine to keep pixel level fidelity between ListView layouts and SGListView layouts. With flexbox styling, removing a cell from a grid can cause a reflow of all remaining cells and therefore could mess with design fidelity. Keeping the bounding box in memory resolved any and all layout concerns.

Why didn't you wrap a UICollectionView / UITableView?

One key goal for this project was to make the final solution platform independent. Using an underlying UICollectionView or UITableView would've tied the implementation to iOS's UIKit and was something we worked to avoid.

Authors

Shaheen Ghiassy [email protected]

Contributing

My attempt will be made to review PRs promptly - but truthfully I'm pretty bad at it.

react-native-sglistview's People

Contributors

cbcye avatar gillpeacegood avatar gre avatar martinosmartinos avatar paramaggarwal avatar sghiassy avatar tsyeyuanfeng 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

react-native-sglistview's Issues

Performance is too low in iPhone5s

my application use SGListView with 300 list items(include text and image), in iPhone 5s after start the memory will be up to more than 300M, but the same application use iPhone 6s the memory is near 100M. any one can give me some suggest ?

Requiring unknown module "SGListView".

Hi @sghiassy. Thanks for building this! Looking forward to trying it out. Sorry to be the first issue....

I'm getting an error when trying to require SGListView
screen shot 2015-08-07 at 6 01 45 pm

I installed via npm install react-native-sglistview --save. I tried restarting the packager, xcode, etc. Did a project -> clean.

Any idea what I might be doing wrong? Thanks!

Duplicate module name: ReactNative

When install the package, packager throws up this error:

Failed to build DependencyGraph: @providesModule naming collision:
  Duplicate module name: ReactNative
  Paths: /{project path here}/node_modules/react-native-sglistview/node_modules/react-native/Libraries/Renderer/src/renderers/native/ReactNative.js 
  collides with /{project path here}/node_modules/react-native/Libraries/react-native/ReactNative.js

I'm using RN 0.36. Any ideas on how to fix the issue? Cheers!

what about flatlist & sectionlist?

This is an awesome work but as official website of RN, Listview has been marked as deprecated and recommend to use Flatlist and Sectionlist.
I am interested in any similar implementation for Flatlist and Sectionlist.
Or will this library make listview as good as other two?
Thanks.

Rest of the cells/rows wont render when using a grid style

<SGListView
  stickyHeaderIndices={[]}
  onEndReached={() => {}}
  onEndReachedThreshold={1}
  pageSize={1}
  initialListSize={10}
  contentContainerStyle={styles.listView}
  dataSource={this.state.dataSource}
  renderRow={this._renderRow}

with this style:

listView: {
    justifyContent: 'flex-start',
    flexDirection: 'row',
    flexWrap: 'wrap',
    paddingTop: 52,
  },

the rest of the rows won't render. In my case the images:

1

npm ERR! cb() never called!

thanks for your smart project first :)

my node version v6.3.1
my npm version v3.10.3

I install failed,

npm install react-native-sglistview --save

output

npm ERR! cb() never called!

what should I do?

thanks for your time.

OnEndReached does not fire in android using SGListView

Hi,

i am trying to load more data while user scroll end of the items using sglistview. but OnEndReched does not fire the event to fetch new setup data to upend to the list. may i know how i can resolve this.? thanks

scrollRenderAheadDistance, stickyHeaderIndices

With RN 0.30.0, warnings appear about the two props mentioned in the title:

 <Warning>: Warning: Failed prop type: Required prop `stickyHeaderIndices` was not specified in `SGListView`.

It's easy to get rid of the warnings by adding the default values (1000 and [], respectively).

This is the relevant bit in the RN code: https://github.com/facebook/react-native/blob/975d196c67dfbe657e9027eb96c9d6ab218c9f17/Libraries/CustomComponents/ListView/ListView.js#L247-L256

Ideally these should not be required props for SGListView as they have default values in the ListView code.

Thanks for the life-saving module!

cannot call static method from DataSource

i got an error

Unhandled JS Exception: _reactNativeSglistview2.default.DataSource is not a constructor

let ds = new SGListView.DataSource({rowHasChanged: (r1, r2) => r1 != r2});

renderScrollComponent prop dose not work

SGListView's renderScrollComponent prop function was not called for me.
Maybe the code should be as below?
if (**this.**props.renderScrollComponent) {
component = **this.**props.renderScrollComponent(props);
} else {
component = _react2.default.createElement(_reactNative.ScrollView, props);
}

Initial render

Hi, thanks for the awesome work ! I'm still having a problem: on the initial render, every cell is rendered ( basically every cell downloads a lot of stuff from the internet) which causes the memory to go very high.
Then when I scroll down, your module makes the off-screen view empty, and I'm memory goes back to a very low level. Then when I go back up again, the memory stays at the same level.

How can I make it not render the off screen views on the initial render ?

zIndex does not work

zIndex does not work with SGListView but it does with ListView. zIndex was introduced in RN29.

Memory issues still happening in android

We have noticed that the memory issues are still persisting in Android. While checking I have found onChangeVisibleRows event is not getting called in android and hence optimisation logics are not working. Is this a known issue or am I missing something. Kindly help.

Enhancement: Pull to refresh.

Currently If I want a pull to refresh I would need to use another react-native library, but since SGListView is the best out there I think if it has a pull to refresh it would be the perfect go to ListView component.

[Android] Custom renderScrollComponent not working?

It seems that using a renderScrollComponent does not work?

I'm aiming to make use of ViewPagerAndroid as a scroll component. Passing a function for that doesn't work as it seems that that specific prop (renderScrollComponent) is not actually resolved by SGListView.

My commit of it here makes it work, however, it causes the whole list to render at once.

Update README premptiveLoading (number)

Just as a suggestion I would add (number) next to the option in the docs so the dev that is implementing the library knows what to pass. In first read I gave it I thought I should pass a boolean.

Can't set a renderSeparator?

I set property renderSeparator. it will return a separator .When I scrolling down first separator out screen.the second cell will gone.
how can I resolve this problem? thx a lot.

<SGListView
                removeClippedSubviews={true}
                renderSeparator={(s,i)=><View style={{backgroundColor:"rgb(240, 240, 240)", height:10}} key={i}></View>}
                dataSource={this.state.dataSource}
                renderRow={this.renderRow}
                initialListSize={3}
                pageSize={10}
                scrollRenderAheadDistance={1}
                renderFooter={this.renderFooter}
                automaticallyAdjustContentInsets={true}
                onEndReachedThreshold={20}
                onEndReached={this.onEnd}
                onChangeVisibleRows={this.onChangeVisibleRows}

                refreshControl={
                    <RefreshControl
                        refreshing={this.state.isRefreshing}
                        onRefresh={this._loadData}
                        tintColor="rgb(100, 100, 100)"
                        title="加载..."
                        colors={['#ff0000', '#00ff00', '#0000ff']}
                        progressBackgroundColor="#ffff00"
                    />
                    }
                />

The Readme is to sample difficult to use

I try to following the steps of Readme to change ListView to SGListView, just change the tag valud and datasource but there has make many error. then to read the example it is difficult to modify for my code. if can hope can make a friendly Readme document

Premature hiding of rows

When scrolling upwards, it uses its performance technique which hides the row but it does it prematurely.

As soon as the bottom of the row touches the bottom of the screen when scrolling up, that row vanishes. I think what it should do instead if hide the row after it scrolls below the bottom edge of the screen, not as soon as it touches it.

State is forgotten when item is re-rendered

I have a list of radio buttons, each can be toggled by tapping. When I toggle a radio button, scroll away and scroll back to it, the radio button resets to the original state. Is this intentional?

EDIT: The radio button's getInitialState sets its toggled state to be on. I'm guessing that when an item leaves the current viewport, it gets destroyed completely and then re-drawn when it comes back into view. Therefore, the item is re-rendered completely getInitialState gets called again.

in ipad is not ok

My rn version is 0.42, i used sglistview on iphone is ok, but in ipad I swipe more than one renderRow distance every cell starts messing around, my ipad version is 9.3.2

renderRow height error

contentContainerStyle={ justifyContent: 'space-around', flexDirection: 'row', flexWrap: 'wrap', } renderRow={ (rowData) => <Image style={width:123, height:200 }} />}

inspect:

ListView ->StaticRenderer
123 x 200

SGListView ->ListView->StaticRenderer
123 x 1600

Rendering bug when using sectionHeaders

I have a rendering bug that doesn't occur with the normal ListView. It occurs when I use section Headers.

After some scrolling, the items start overlapping each other. I'm assuming that the trick with emptying out invisible boxes is not taking sections into consideration.

screen shot 2016-10-17 at 17 31 59

screen shot 2016-10-17 at 17 31 48

I call SGListView like so

  <SGListView
      ref="sglist"
      automaticallyAdjustContentInsets={false}
      dataSource={this.state.ds}
      renderRow={renderRow}
      contentContainerStyle={this.props.contentContainerStyle}
      stickyHeaderIndices={[]}
      initialListSize={this.props.initialListSize}
      scrollRenderAheadDistance={1}
      pageSize={12}
      scrollEnabled={scrollEnabled}
      onScroll={onScroll}
      scrollEventThrottle={0}
      onMomentumScrollEnd = {onScrollEnd}
      onEndReached={this.handleLoadMore}
      onEndReachedThreshold={70}
      renderSectionHeader={this.props.renderSectionHeader}
      renderFooter={this.renderFooter}
      contentContainerStyle={[localStyle.container,contentContainerStyle]}
      onLayout={this.setListHeight}
      refreshControl={
        <RefreshControl
          refreshing={showRefresh}
          onRefresh={onRefresh}
        />
      }
  />

Some props are not implemented

I tried your component, it does not work because I'm using the following which are not defined:
scrollProperties
getScrollResponder()

Add more maintainers

The idea of this package is great, but there are still some bugs on it

the development is stopped since last August, would be good to add more maintainers to help review Pull requests and help fix issues

Please Provide Compiled Versions

Hi there,

This is great! My only concern is that I exclude node_modules. I can whitelist this package but it would be great if there were a compiled version we can use.

Thank you,
Peter

scrollTo is not a function

I was hoping for SGListview to be a drop in replacement for ListView. I'm using the scrollTo method to scroll to different portions of the list. Is this not support with SGListview?

Scrolling fast causes some rows to stay hidden

I notice when I scroll fast that some rows don't get set to be visible again... Also when data is added to DataSource (infinite scrolling) sometimes the first new row is hidden when it should be showing

onLayout only called on initial render

I've noticed that the onLayout event is only called on the initial render, but not when additional rows are added. Not sure if this is a bug in sglistview or the underlying listview

Cells remain visible in premptiveLoading

Hi @sghiassy thank you for this wonderful component. I have been using a similar implementation, but never got around to pulling it out into a library and open sourcing it. Also, I like your method to use refs to the individual cells. In my case, I was trying to handle everything at the ListView layer itself.

I had been trying to implement something like premptiveLoading in my implementation and was hitting an issue where some cell would be pre-emptively made visible, but if you started scrolling in the other direction they would simply remain visible. This unfortunately is happening in your implementation too.

Here is a screenshot of my view hierarchy. I scrolled down and then scrolled up. You can see the current viewport in the screenshot below. The two stray cards at the bottom are the ones that were pre-emptively rendered but never hidden again.

screen shot 2015-08-14 at 6 52 09 am

Here is the snippet of code that causes this:

// Preemptivly set cells
    for (var i = 1; i <= props.premptiveLoading; i++) {
      var cell;

      if (isScrollingUp){
        cell = cellData[section][lastRow - i];
      } else if (isScrollingDown) {
        cell = cellData[section][lastRow + i];
      }

      if (cell) {
        cell.setVisibility(true);
      } else {
        break;
      }
    }

Here you will notice that a cell on which we call setVisibility(true) is never set back to not be visible if we start scrolling in the opposite direction! I have forked your library into my project and will continue making some modifications for this and other things and will come back with a PR. Thanks again!

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.