Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ListView leaks memory and doesn't clean up (Android) #12512

Closed
jasongrishkoff opened this issue Feb 22, 2017 · 30 comments
Closed

ListView leaks memory and doesn't clean up (Android) #12512

jasongrishkoff opened this issue Feb 22, 2017 · 30 comments
Labels
Resolution: Locked This issue was locked by the bot.

Comments

@jasongrishkoff
Copy link

jasongrishkoff commented Feb 22, 2017

Hi there, I'm using RN 0.41.2 on an Android device (not emulator). I've created a really simple ListView component. As I scroll down this list, the memory used by the app increases linearly. If I background the app, this memory doesn't get cleaned up at all.

While the code below is simple, you can imagine how out-of-hand this gets on a ListView that renders more-detailed rows (including Image and TouchableOpacity). The problem is that the app I'm building is a music streaming app. If I scroll through ~3 pages of tracks, it bring the app's total consumption up to ~150MB of ram (from an initial boot of 90MB), which makes it the #1 candidate for Android to garbage collect if another app takes the foreground and requires more memory (eg, you want to browse Chrome while listening to the music app in the background). Without the ListView, my app uses up ~55MB -- a number similar to the one generated by the simple component below.

I've tried this with the new/experimental FlatList component, and I get similar - if not worse - results as far as memory consumption. This is the main thing holding me back from rolling out my React Native version to production (on an app with 500,000+ installs).

import React, { Component } from 'react';
import {
  AppRegistry,
  Text,
  ListView
} from 'react-native';

var data = []
for (var ii = 0; ii < 1000; ii++) {
    data.push('row - ' + ii)
}

export default class AwesomeProject extends Component {
  constructor() {
    super();
    const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
    this.state = {
      dataSource: ds.cloneWithRows(data),
    };
  }

  render() {
    return (
      <ListView
        dataSource={this.state.dataSource}
        initialListSize={50}
        pageSize={50}
        renderRow={(rowData) => <Text>{rowData}</Text>}
      />
    );
  }
}

AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);

Screenshots below created using "adb shell dumpsys meminfo -a com.awesomeproject"

snapshot1
snapshot2
snapshot3
snapshot4

@jasongrishkoff jasongrishkoff changed the title ListView leaks memory and doesn't clean up (Anroid) ListView leaks memory and doesn't clean up (Android) Feb 22, 2017
jasongrishkoff referenced this issue Feb 22, 2017
Summary:
We really need a better list view - so here it is!

Main changes from existing `ListView`:

* Items are "virtualized" to limit memory - that is, items outside of the render window are unmounted and their memory is reclaimed. This means that instance state is not preserved when items scroll out of the render window.
* No `DataSource` - just a simple `data` prop of shape `Array<any>`. By default, they are expected to be of the shape `{key: string}` but a custom `rowExtractor` function can be provided for different shapes, e.g. graphql data where you want to map `id` to `key`. Note the underlying `VirtualizedList` is much more flexible.
* Fancy `scrollTo` functionality: `scrollToEnd`, `scrollToIndex`, and `scrollToItem` in addition to the normal `scrollToOffset`.
* Built-in pull to refresh support - set set the `onRefresh` and `refreshing` props.
* Rendering additional rows is usually done with low priority, after any interactions/animations complete, unless we're about to run out of rendered content. This should help apps feel more responsive.
* Component props replace render functions, e.g. `ItemComponent: ReactClass<{item: Item, index: number}>` replaces `renderRow: (...) => React.Element<*>`
* Supports dynamic items automatically by using `onLayout`, or `getItemLayout` can be provided for a perf boost and smoother `scrollToIndex` and scroll bar behavior.
* Visibility callback replaced with more powerful viewability callback and works in vertical and horizontal mode on at least Android and iOS, but probably other platforms as well. Extra power comes from the `viewablePercentThreshold` that lets the client decide when an item should be considered viewable.

Demo:

https://www.facebook.com/groups/576288835853049/permalink/753923058089625/

Reviewed By: yungsters

Differential Revision: D4412469

fbshipit-source-id: e2d891490bf76fe14df49294ecddf78a58adcf23
@booboothefool
Copy link

booboothefool commented Feb 22, 2017

Same issue, except my app is actually in production and all my Android users are pissed giving me 1 star reviews, some in particular complaining about the memory usage. 😝 The more I scroll down the list, the slower the app becomes. List items include Image and TouchableOpacity, which like the OP said, makes it even worse.

@brentvatne
Copy link
Collaborator

Hello! What you are describing here is (sadly) the intended behavior of react-native's ListView component on iOS and Android -- it does not recycle views or unmount anything that goes out of view, with the exception of images if you use removeClippedSubviews. I see you looked into FlatList @jasongrishkoff -- that should help with this problem because it uses windowing -- only the contents you can currently see and some buffer around the contents are actually rendered.

@booboothefool
Copy link

booboothefool commented Feb 22, 2017

Hey @brentvatne,

@jasongrishkoff mentioned FlatList didn't help the memory issues. I just tried it myself as well, and got similar results. I can see the windowing happening, however the same issue applies where the more I scroll down my list (infinite scrolling) to display more rows, the slower my app becomes.

Anything else worth trying?

@brentvatne
Copy link
Collaborator

@booboothefool - is there anything else in your app that would make it slower? like maybe each row is subscribing to redux events? I'd try profiling your app to see where the slowness is coming from

@sahrens
Copy link
Contributor

sahrens commented Feb 23, 2017

Your memory usage low enough that the garbage collector might not even be kicking in, depending on the device you're running on. Try rendering more like 10000 rows and see if the memory continues to increase linearly or if it ever actually runs out of memory and crashes.

@sahrens
Copy link
Contributor

sahrens commented Feb 23, 2017

As for slowness, I agree with @brentvatne that there is probably something else going on.

@jasongrishkoff
Copy link
Author

Right, so I've got FlatList working using the very basic example provided in FlatListExample.js + ListExampleShared.js. No other modules or fancy things in my project -- it's a fresh install. The only thing I did was remove the thumbnails from the example.

EXAMPLE 1 WITH VIRTUALIZED = TRUE AND fixedHeight = TRUE
Initial app load: 78MB
Two swipes of scrolling (takes me to item #148): 108MB
An additional two swipes (takes me to #245): 131MB
Two more swipes (takes me to #385): 138MB
Two more swipes (takes me to #545): 132MB (woo, something flatlined!)

Okay from there, it tends to hover around 132MB -- which is too high and will get killed by Android as soon as I started to use other apps (I'm on a Nexus 5X, so not a bad phone). Sure enough, I opened Gmail, then WhatsApp, and my AwesomeProject was cleaned in the background.

Also note that scrolling was a bit choppy. I'd move down the feed and it'd sorta take a while to gather its positioning.

EXAMPLE 2 WITH VIRTUALIZED = TRUE AND fixedHeight = FALSE
Initial app load: 72MB
Two swipes of scrolling (takes me to item #143): 100MB
An additional two swipes (takes me to #280): 121MB
Two more swipes (takes me to #370): 137MB
Two more swipes (takes me to #457): 136MB (woo, something flatlined!)

So, in both cases it stopped hemorrhaging memory around the ~137MB mark. But again, that's way too high.

@booboothefool
Copy link

booboothefool commented Feb 24, 2017

Does this look normal to you guys?

(before and after scrolling an infinite list of user pictures)

screen shot 2017-02-24 at 12 20 29 pm

If you guys would like, I could just tell you what the app is so you can download it off the Google Play Store and see for yourself how it just becomes slower the more you scroll (email me at meatyoaker001@gmail.com).

@jasongrishkoff
Copy link
Author

Wow, yours is using an incredible amount of memory -- but still shows the same trend that I'm experiencing. One thing I see at an extreme level on yours is the # of Views.

@sahrens
Copy link
Contributor

sahrens commented Feb 24, 2017

@booboothefool that's with FlatList? Something is definitely broken there. Sample code would be helpful.

@brentvatne brentvatne reopened this Feb 24, 2017
@booboothefool
Copy link

booboothefool commented Feb 25, 2017

The previous screenshot was with ListView and my full app. It took a while, but I stripped down the code a lot to make this using FlatList (love the simple new props btw!), which includes getting rid of my images and just rendering text. I did notice a minor performance improvement. It's like my app slows down to the point where it's annoying and isn't smooth, but it doesn't slow down to the point where it's completely unusable wtf worst app ever 1 star memory leaks Q.Q /uninstall lol.

How does this look? Here are the results stripping out a bunch of stuff, using FlatList, before and after scrolling to the end of my list (2000+ results):

screen shot 2017-02-25 at 1 51 08 am

Sample code:

import Config from 'react-native-config';
import config from './config';
import React, { Component } from 'react';
import {
  View,
  Dimensions,
  TouchableOpacity,
} from 'react-native';
import {
  Container,
  Content,
  Text,
} from 'native-base';
import { Actions } from 'react-native-router-flux';
import ScrollableTabView, { ScrollableTabBar } from 'react-native-scrollable-tab-view';
import FlatList from 'react-native/Libraries/Experimental/FlatList';
import myTheme from './myTheme';
import EStyleSheet from 'react-native-extended-stylesheet';

const deviceWidth = Dimensions.get('window').width;
const deviceHeight = Dimensions.get('window').height;
const styles = EStyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#F1F0FF',
    paddingBottom: '3.4rem',
  },
  card: {
    backgroundColor: 'white',
    borderRadius: 22,
  },
  cardWidth: {
    width: deviceWidth / 2 - (2 * 5),  // padding = # per row * cardHeight margin
  },
  cardHeight: {
    height: '35%',
    alignItems: 'center',
    margin: 5,
  },
  cardShadow: {
    shadowColor: '#3F51B5',
    shadowOffset: { width: 0, height: 3 },
    shadowOpacity: 0.3,
    shadowRadius: 3,
    elevation: 3,
  },
});

var algoliasearch = require('algoliasearch/reactnative');
var algoliasearchHelper = require('algoliasearch-helper');
var client = algoliasearch(Config.ALGOLIASEARCH_APPLICATION_ID, Config.ALGOLIASEARCH_API_KEY_SEARCH);

const helper = algoliasearchHelper(client, 'users', {
  hitsPerPage: 12,
});

const Match = ({ hit }) => {
  return (
    <TouchableOpacity style={[styles.cardWidth]} onPress={() => Actions.profile({ hit })}>
      <View style={[{ marginTop: 8 }, styles.cardHeight]}>
        <Text>{hit.Birthday}</Text>
      </View>
    </TouchableOpacity>
  );
};

class Tab extends Component {
  constructor(props) {
    super(props);
  }

  renderItemComponent({ item, index }) {
    return (
      <View key={item.objectID} style={[styles.card, styles.cardWidth, styles.cardHeight, styles.cardShadow]}>
        <Match
          hit={item}
        />
      </View>
    );
  }

  render() {
    return (
      <FlatList
        data={this.props.hits}
        ItemComponent={(item, index) => this.renderItemComponent(item, index)}
        numColumns={2}
        onEndReached={() => helper.setPage(helper.getPage() + 1).search()}
        windowSize={(deviceHeight * 0.35) * 2}  // 2 rows of cards, I also tried the default props
      />
    );
  }
}

class Browse extends Component {
  constructor(props) {
    super();

    this.state = {
      currentTab: 'discover',
      hits: {
        discover: [],
      },
    };

    helper.on('result', (content) => {
      let currentHits = this.state.hits[this.state.currentTab];
      this.setState({
        hits: {
          [this.state.currentTab]: content.page === 0 ? content.hits : currentHits.concat(content.hits),
        },
      });
    });
  }

  componentWillMount() {
    helper.setQueryParameter('aroundLatLng', '38.8993277,-77.0846061');
    helper.search();
  }

  componentWillUnmount() {
    helper.removeAllListeners('result');
  }

  render() {
    return (
      <Container style={styles.container} theme={myTheme}>
        <Content scrollEnabled={false} contentContainerStyle={{ flex: 1 }}>

          <ScrollableTabView
            initialPage={0}
            renderTabBar={() => <ScrollableTabBar />}
          >

            <Tab key="discover"
              tabLabel="Discover"
              hits={this.state.hits.discover}
            />

          </ScrollableTabView>

        </Content>
      </Container>
    );
  }
}

export default Browse;

UPDATE: Here is another example of my full app using FlatList:
screen shot 2017-02-26 at 2 12 35 am

@sahrens
Copy link
Contributor

sahrens commented Mar 2, 2017

So windowSize is in units of visible length, typically screens, so where you set windowSize={(deviceHeight * 0.35) * 2} you're setting the render window to hundreds of screens worth of content, which is over 10x the default value and basically zero windowing at all and would perfectly explain the behavior you're seeing.

You have a comment that says you tried the default value - were the memory and view numbers exactly the same in that case? I would expect the default to work much better and save your memory. You can also set debug={true} and get a visualization overlay that should help show what's going on.

@booboothefool
Copy link

booboothefool commented Mar 2, 2017

@sahrens I hope I'm that stupid. XD Maybe I was just imagining using the default props? :) Either way I think something changed:

Using this code:

import Config from 'react-native-config';
import config from './config';
import React, { Component } from 'react';
import {
  View,
  Dimensions,
  TouchableOpacity,
} from 'react-native';
import {
  Container,
  Content,
  Text,
} from 'native-base';
import { Actions } from 'react-native-router-flux';
import ScrollableTabView, { ScrollableTabBar } from 'react-native-scrollable-tab-view';
import FlatList from 'react-native/Libraries/CustomComponents/Lists/FlatList';
import myTheme from './myTheme';
import EStyleSheet from 'react-native-extended-stylesheet';

const deviceWidth = Dimensions.get('window').width;
const deviceHeight = Dimensions.get('window').height;
const styles = EStyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#F1F0FF',
    paddingBottom: '3.4rem',
  },
  card: {
    backgroundColor: 'white',
    borderRadius: 22,
  },
  cardWidth: {
    width: deviceWidth / 2 - (2 * 5),  // padding = # per row * cardHeight margin
  },
  cardHeight: {
    height: '35%',
    alignItems: 'center',
    margin: 5,
  },
  cardShadow: {
    shadowColor: '#3F51B5',
    shadowOffset: { width: 0, height: 3 },
    shadowOpacity: 0.3,
    shadowRadius: 3,
    elevation: 3,
  },
});

var algoliasearch = require('algoliasearch/reactnative');
var algoliasearchHelper = require('algoliasearch-helper');
var client = algoliasearch(Config.ALGOLIASEARCH_APPLICATION_ID, Config.ALGOLIASEARCH_API_KEY_SEARCH);

const helper = algoliasearchHelper(client, 'users', {
  hitsPerPage: 12,
});

const Match = ({ hit }) => {
  return (
    <TouchableOpacity style={[styles.cardWidth]} onPress={() => Actions.profile({ hit })}>
      <View style={[{ marginTop: 8 }, styles.cardHeight]}>
        <Text>{hit.Birthday}</Text>
      </View>
    </TouchableOpacity>
  );
};

class Tab extends Component {
  constructor(props) {
    super(props);
  }

  _renderItemComponent = ({ item }) => {
    return (
      <View key={item.objectID} style={[styles.card, styles.cardWidth, styles.cardHeight, styles.cardShadow]}>
        <Match
          hit={item}
        />
      </View>
    );
  }

  render() {
    return (
      <FlatList
        data={this.props.hits}
        renderItem={this._renderItemComponent}
        onEndReached={() => helper.setPage(helper.getPage() + 1).search()}
        numColumns={2}
        debug={this.props.hits.length > 0}
      />
    );
  }
}

class Browse extends Component {
  constructor(props) {
    super();

    this.state = {
      currentTab: 'discover',
      hits: {
        discover: [],
      },
    };

    helper.on('result', (content) => {
      let currentHits = this.state.hits[this.state.currentTab];
      this.setState({
        hits: {
          [this.state.currentTab]: content.page === 0 ? content.hits : currentHits.concat(content.hits),
        },
      });
    });
  }

  componentWillMount() {
    helper.setQueryParameter('aroundLatLng', '38.8993277,-77.0846061');
    helper.search();
  }

  componentWillUnmount() {
    helper.removeAllListeners('result');
  }

  render() {
    return (
      <Container style={styles.container} theme={myTheme}>
        <Content scrollEnabled={false} contentContainerStyle={{ flex: 1 }}>

          <ScrollableTabView
            initialPage={0}
            renderTabBar={() => <ScrollableTabBar />}
          >

            <Tab key="discover"
              tabLabel="Discover"
              hits={this.state.hits.discover}
            />

          </ScrollableTabView>

        </Content>
      </Container>
    );
  }
}

export default Browse;

I made a video of the debug={true}: https://www.youtube.com/watch?v=wlQmzICT3j0
after watching it, I assume the green box is the window?

and here are the results shown at the end of the video:
screen shot 2017-03-02 at 12 40 17 am

I definitely noticed a performance improvement. The memory and views are going up, however my app isn't turning to complete mush anymore. Overall, I think I can work with this.

Does everything look right to you from my code / video / screenshot? What about you, @jasongrishkoff ?

@jasongrishkoff
Copy link
Author

@booboothefool your memory usage went from 186mb to 359mb -- that's very high, and it's likely that as soon as you move to another app, Android will automatically garbage collect your app.

@booboothefool
Copy link

booboothefool commented Mar 2, 2017

Yeah, seems like I spoke a bit too soon. Noticed the app slowed down a ton once I added everything else back (images, ads, calculations e.g. Birthday -> Age). (I'll make another video when I wake up. The slowdown is noticeable by just adding images )

@sahrens
Copy link
Contributor

sahrens commented Mar 2, 2017

Yeah, 400MB is still a little high - what device are you running on? The heap and cache sizes will vary depending on the device memory. The view count is much more reasonable, but also a bit high. You can try dialing down the windowSize too. The default is 21 which is actually quite large.

But note that the live memory number is going to be much higher than the background number. That 359mb includes GPU texture buffers and other caches that should be cleared when the app is backgrounded. It also might take a while for the JS Garbage collector to trigger a cleanup and release the memory back to the operating system.

Memory is a very complex issue. Have you tried doing similar analysis with other apps? What happens if you scroll through the same amount of content in the other apps, like Twitter?

@booboothefool
Copy link

booboothefool commented Mar 3, 2017

@sahrens Hello friend. Thanks for your response. ^^

I am using a Samsung Galaxy S6 running Android 6.

I tried adding some of my pictures back and besides that, the only code change to FlatList was:

windowSize={3}

I noticed that using a smaller windowSize instead of the default definitely reduced the lag with the scrolling. It scrolls smoothly for the most part.
https://www.youtube.com/watch?v=JgkeojJLmmA
Here's the data:
screen shot 2017-03-02 at 9 07 46 pm
It looks like the number of views definitely stays low even after all that scrolling, however the memory is unaffected.

Another issue I'm seeing is that using SeparatorComponent, even with a simple text separator, causes a lot of stuttering.

  _renderSeparatorComponent = () => {
    return (
      <Text>{'yurrrppp!! >.<"'}</Text>
    );
  }

https://www.youtube.com/watch?v=y1HDH5wkFT0

On my live app, I am rendering an ad every 12 items using ListView. With FlatList, I am finding myself running into a lot more trouble doing this than anticipated. XD

@sahrens
Copy link
Contributor

sahrens commented Mar 3, 2017

Does ListView not use more memory than FlatList? Or is FlatList better on memory, but more sluggish than ListView? Wth a gigantic windowSize, like you had before, or with enableVirtualization={false}, they should have pretty similar performance. Also note that debug is a massive perf hit, so make sure to turn that off (and also make sure you are not in __DEV__ mode) when you are evaluating performance.

Some more perf tips:

  • Try implementing shouldItemUpdate. I don't know what your helper thing is doing, but ideally you can do === reference checks on the results it gives back to tell if they have changed, otherwise you might want to compare the object ids if the results themselves are unlikely to change? Depends on your product logic.
  • Shadows can be quite expensive to render - does it help to get rid of them? If it helps a lot, then you should use a shadow image asset instead of generating them programatically.
  • What does it mean for your card height to be 35% when they are inside an infinite list? That seems a little weird and might affect perf?

@jasongrishkoff
Copy link
Author

jasongrishkoff commented Mar 3, 2017 via email

@sahrens
Copy link
Contributor

sahrens commented Mar 3, 2017 via email

@jasongrishkoff
Copy link
Author

jasongrishkoff commented Mar 3, 2017

We're getting into unrelated territory, but how does one toss views and context on background? Just monitor AppState and set the main component to be null when state is background? Right now I'm using mobx + react-native-music-control to handle the playlist component, and it works just fine when the app is backgrounded. It's just that the app doesn't shed any memory -- it hangs around 100mb+, and I reckon I'd need to get it down to ~75mb to convince Android not to kill it quickly.

@sahrens
Copy link
Contributor

sahrens commented Mar 3, 2017

That might help, yeah. You also might want to do some research on native Android development and might have to write some Java to get a world-class music player experience. Have you built anything similar with something like Cordova? How does it fair memory-wise, especially in the background?

@sahrens
Copy link
Contributor

sahrens commented Mar 3, 2017

I think music playback should also keep your app prioritized and less likely to get killed by the OS in the background. Are you seeing otherwise? Might want to reach out to the react-native-music-control maintainers, or ask on stack overflow.

@jasongrishkoff
Copy link
Author

jasongrishkoff commented Mar 3, 2017

Edit Going to play around with this in release variant a bit more - results below were with dev.

The music player experience is pretty solid -- they've done a great job with the aforementioned library. My only problem right now is that my React Native app is quite lean (122 views on fully-loaded home screen according to meminfo), and yet still uses more memory than any other app on my Android device -- even when it's just a basic project (~70MB) with no FlatList or navigation or anything imported at all. A straight-up Hello is all. WhatsApp for comparison idles at 25MB and when active tends to peak around 75MB.

If my baseline for a nothing-app is 70mb, it's problematic because anything I add from there is going to increase it.

I also observe that when I've backgrounded my app, the amount of memory being used is barely reduced -- maybe 5% over the course of ~20 seconds. If I was using 120MB in the foreground, this means a background app ends up holding onto ~114MB, which puts it at the top of the stackrank of apps open on the Android device, and therefore #1 to be killed if the OS needs to free up memory for another app.

Setting the main component to = null brings the # of Views displayed in meminfo from 122 down to 7... and yet the memory still only goes down 5%.

Sorry for going so off-tangent given this was originally a ListView conversation. My testing so far indicates that the memory leak issue has been solved by FlatList, which eliminates a huuuge bottleneck. Just need to get the baseline down, or figure out how to shed memory when backgrounded.

@sahrens
Copy link
Contributor

sahrens commented Mar 3, 2017 via email

@RichardLindhout
Copy link

Maybe related to #11809?

@joshjhargreaves
Copy link
Contributor

joshjhargreaves commented Mar 27, 2017

I played around with FlatList on iOS with 'full-screen' images in a list and a small windowSize of 3. Memory usage climbs linearly until it hits a threshold where it no longer increases. From enabling debug it it would appear it initially renders a few pages worth of views before the 'windowing' behavior kicks in (nice to see this behavior working :)); the debug visuals would suggest these initial views are never removed.

Video of the behavior: https://www.youtube.com/watch?v=s_YUMfb__ms

@sahrens I'm not sure if you've any thoughts? :)

edit: my mistake, it looks like I just described the VirtualizedList prop 'initialNumToRender' exactly!

@sahrens
Copy link
Contributor

sahrens commented Mar 27, 2017

Sounds like you're still using the default initialNumToRender of 10 - try setting initialNumToRender={2} to reduce peak memory consumption. It's documented in the underlying VirtualizedListView, but I should probably add it to the FlatList documentation since it's a pretty important prop.

I should also add to the docs that the initialNumToRender items are never removed. This improves the perceived perf of scrolling back to the top of the content because you don't have to wait for it to render.

@joshjhargreaves
Copy link
Contributor

facebook-github-bot pushed a commit that referenced this issue Mar 28, 2017
… `initialNumToRender`

Summary: Should help with some common pitfalls, e.g. #12512 (comment).

Reviewed By: yungsters

Differential Revision: D4781833

fbshipit-source-id: 3dec2f0c444645ad710e9ed81390636da4581f0f
karanjthakkar pushed a commit to karanjthakkar/react-native that referenced this issue Mar 28, 2017
… `initialNumToRender`

Summary: Should help with some common pitfalls, e.g. facebook#12512 (comment).

Reviewed By: yungsters

Differential Revision: D4781833

fbshipit-source-id: 3dec2f0c444645ad710e9ed81390636da4581f0f
thotegowda pushed a commit to thotegowda/react-native that referenced this issue May 7, 2017
… `initialNumToRender`

Summary: Should help with some common pitfalls, e.g. facebook#12512 (comment).

Reviewed By: yungsters

Differential Revision: D4781833

fbshipit-source-id: 3dec2f0c444645ad710e9ed81390636da4581f0f
@hramos
Copy link
Contributor

hramos commented Jul 25, 2017

Hi there! This issue is being closed because it has been inactive for a while. Maybe the issue has been fixed in a recent release, or perhaps it is not affecting a lot of people. Either way, we're automatically closing issues after a period of inactivity. Please do not take it personally!

If you think this issue should definitely remain open, please let us know. The following information is helpful when it comes to determining if the issue should be re-opened:

  • Does the issue still reproduce on the latest release candidate? Post a comment with the version you tested.
  • If so, is there any information missing from the bug report? Post a comment with all the information required by the issue template.
  • Is there a pull request that addresses this issue? Post a comment with the PR number so we can follow up.

If you would like to work on a patch to fix the issue, contributions are very welcome! Read through the contribution guide, and feel free to hop into #react-native if you need help planning your contribution.

@hramos hramos added the Icebox label Jul 25, 2017
@hramos hramos closed this as completed Jul 25, 2017
@facebook facebook locked as resolved and limited conversation to collaborators Jul 25, 2018
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Jul 25, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests

9 participants