Giter Club home page Giter Club logo

react-native-masonry-list's Introduction

@appandflow/masonry-list

npm (scoped) Travis branch

Allows creating masonry style list layouts in a performant way.

This component leverages FlatList to render performant masonry layout lists. The main caveat right now is that it doesn't support measuring cells (yet) so you need to be able to provide the dimensions.

Installation

yarn add @appandflow/masonry-list

Usage

import MasonryList from '@appandflow/masonry-list';

Props

This component supports most of the props of FlatList plus a few extras one:

getHeightForItem: ({ item: any, index: number }) => number,

Returns the height for a specific item. Note that this it not optional for now.

numColumns: number

The number of columns.

renderItem: ({ item: any, index: number, column: number }) => ?ReactElement<*>,

Same as renderItem from FlatList but also gets passed the column index.

Example

Play with on Expo

Take a look at example folder

TODO

  • Support measuring items automatically and get rid of getHeightForItem.

  • Implement onEndReached in a way that it isn't called multiple times.

  • Support FooterComponent.

  • Long term, could probably be implemented without using multiple VirtualizedList to make it more performant and less hacky.

react-native-masonry-list's People

Contributors

assertchris avatar cesardeazevedo avatar janicduplessis avatar juangl avatar oblador 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

react-native-masonry-list's Issues

Pull to refresh not working

Pull to refresh feauture not working

_onRefresh=()=> { this.setState({refreshing: true}); const{username}=this.state; this.props.getInspiration({username,offset:0}) .then(r=>{ this.setState({posts.data.posts,refreshing: false}) }); }

<MasonryList onRefresh={this._onRefresh} refreshing={this.state.refreshing} horizontal={false} onEndReached={this._onLoadMore} keyExtractor={this._keyExtractor} numColumns={2} getHeightForItem={() => 1} data={this.state.posts} renderItem={(item)=><Card auser={this.state.username} item={item}/>} />

If i set refreshing=true, the loading indicator shows, however when I pull to call my _onRefresh function, nothing happens.

Not rendering data in two columns

I am using this library in one of my projects. Earlier I was using flatlist. I am displaying data in 2 columns. But when I use this library data is only display in one column.

`

                    <MasonryList
                        onRefresh={this.state}
                        data={this.state.postsArray}
                        renderItem={this.renderRowItem}
                        getHeightForItem={({ item }) => item.height + 2}
                        numColumns={2}
                        keyExtractor={this._keyExtractor}
                        
                    />`

`renderRowItem = (itemData) => {

    console.log("Image url" + itemData.item.type);
    if (itemData.item.type === 'image') {
        console.log("Flatlist Image");
        return (
            <View style={styles.row}>
                <Image source={{ uri: itemData.item.url }} style={[styles.image]} />
                <View style={{ backgroundColor: 'white', padding: 15, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-around',borderTopColor: '#eaeaea',
                borderTopWidth: 1, }}>
                    <View style={styles.iconCountContainer} onPress={() => { ToastAndroid.show('Liked', ToastAndroid.SHORT); }}>
                        <Icon active name="favorite" style={styles.like} size={14} onPress={() => { ToastAndroid.show('Liked', ToastAndroid.SHORT); }} />
                    </View>
                    <View style={styles.iconCountContainer} onPress={() => Share.open(shareOptions).catch((err) => { err && console.log(err); })}>
                        <Icon active name="share" size={14} style={styles.share} onPress={() => Share.open(shareOptions).catch((err) => { err && console.log(err); })} />
                    </View>
                </View>
            </View>
        )
    }
    else if (itemData.item.type === 'video') {
        console.log("Flatlist Video");
        return (
            <View style={styles.row}>
                <VideoPlayer video={{ uri: itemData.item.url }} style={[styles.video]} />
                <View style={{ backgroundColor: 'white', padding: 15, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-around' ,borderTopColor: '#eaeaea',
 borderTopWidth: 1,}}>
                    <View style={styles.iconCountContainer} onPress={() => { ToastAndroid.show('Liked', ToastAndroid.SHORT); }}>
                        <Icon active name="favorite" style={styles.like} size={14} onPress={() => { ToastAndroid.show('Liked', ToastAndroid.SHORT); }} />
                    </View>
                    <View style={styles.iconCountContainer} onPress={() => Share.open(shareOptions).catch((err) => { err && console.log(err); })}>
                        <Icon active name="share" size={14} style={styles.share} onPress={() => Share.open(shareOptions).catch((err) => { err && console.log(err); })} />
                    </View>
                </View>
            </View>
        )
    }

    else if (itemData.item.type === 'blog') {
        console.log("Flatlist Blog");
        return (
            <View style={styles.blog}>
                <Image source={{ uri: itemData.item.url }} style={[styles.image]} />
                <View style={{ flexDirection: 'column',width:162.5}}>
                    <Text style={{textAlign: 'center'}}>{itemData.item.text}</Text>
                </View>
                <View style={{ backgroundColor: 'white', padding: 15, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-around' }}>
                    <View style={styles.iconCountContainer} onPress={() => { ToastAndroid.show('Liked', ToastAndroid.SHORT); }}>
                        <Icon active name="favorite" style={styles.like} size={14} onPress={() => { ToastAndroid.show('Liked', ToastAndroid.SHORT); }} />
                    </View>
                    <View style={styles.iconCountContainer} onPress={() => Share.open(shareOptions).catch((err) => { err && console.log(err); })}>
                        <Icon active name="share" size={14} style={styles.share} onPress={() => Share.open(shareOptions).catch((err) => { err && console.log(err); })} />
                    </View>
                </View>
            </View>
        )
    }

    else if (itemData.item.type === 'audio') {
        console.log("Flatlist Audio");
        return (
            <View style={[styles.row]}>
                <View style={styles.audio}>
                    <Player  url={"http://lacavewebradio.chickenkiller.com:8000/stream.mp3"} />
                </View>
                <View style={{ backgroundColor: 'white', padding: 15, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-around' }}>
                    <View style={styles.iconCountContainer} onPress={() => { ToastAndroid.show('Liked', ToastAndroid.SHORT); }}>
                        <Icon active name="favorite" style={styles.like} size={14} onPress={() => { ToastAndroid.show('Liked', ToastAndroid.SHORT); }} />
                    </View>
                    <View style={styles.iconCountContainer} onPress={() => Share.open(shareOptions).catch((err) => { err && console.log(err); })}>
                        <Icon active name="share" size={14} style={styles.share} onPress={() => Share.open(shareOptions).catch((err) => { err && console.log(err); })} />
                    </View>
                </View>
            </View>
        )
    }
}`

This is stylesheet content for above components

image: {
height: 200,
width: 150,
resizeMode: 'cover',
borderTopLeftRadius: 3,
borderTopRightRadius: 3,
},
video: {
height: 200,
width: 150,
borderTopLeftRadius: 3,
borderTopRightRadius: 3,
},
audio: {
height: 200,
width: 150,
borderTopLeftRadius: 3,
borderTopRightRadius: 3,
},
row: {

    marginTop:10,
    marginRight:10 ,
    borderRadius: 3,
    backgroundColor: '#fff',
    shadowColor: '#303030',
    shadowOffset: {
        width: 0,
        height: 2
    },
    shadowOpacity: 0.1
},
blog: {
    marginTop:10,
    marginRight: 10,
    borderRadius: 3,
    backgroundColor: '#fff',
    shadowColor: '#303030',
    shadowOffset: {
        width: 0,
        height: 2
    },
    shadowOpacity: 0.1
},

Use ListHeaderComponent

Hi !
I'm new with react native, i search now for 3hours and i don't no how to send data into the ListHeaderComponent.
because in my code I use :
<MasonryList ListHeaderComponent={this.RenderMasonryHeader} ...
and my RenderMasonryHeader is :
RenderMasonryHeader(state) { return ( <View> <CachedImage source={{ uri: this.props.avatar }}/> </View>

And I don't know how to send to this.props.
Please help meeee

Two footer views

I have a MasonryList with 2 columns, and I defined a footer component in the list:
ListFooterComponent={() => (<MyFooterComponent />)}
When i I run the code, I got 2 footer views on 2 columns. Any ideas ?

Support measuring items automatically

Hello, everyone!

I'd like to implement this feature, unfortunately, I'm not pretty sure how to do that. What would be the implications of not using getItemLayout with the actual code?

Still performance issue.

I have battle tested with same logic with this library but it doesn't work. I guess it takes time for calculating column height.

After almost 100 data rendered JS thread fps right away down to 7.

getHeightForItem

Support measuring items automatically and get rid of getHeightForItem.----------Wish you an early plan

numColumns={3} not working for datalist

Here is my code,
<MasonryList data={products}
renderItem={({ item }) => }
sorted
getHeightForItem={({ item }) => item.height + 2}
numColumns={3}
keyExtractor={this._keyExtractor}
onEndReached={this.handleLoadMore}
/>

Encountered children with the same key

I am using MasonryList to show a list which can be switched between 1 and 2 columns. When there is just 1 column, it works normally without any errors or warnings. However, when I switch to 2 columns mode and scroll the list up, there are warnings prompting "Warning: flattenChildren(...): Encountered children with the same key".
In the keyExtractor function, I return the id of the the item. I dont think there are items with the same id.
I am a beginner in react native. So I have no idea where does this error comes from.
Please help me. Thanks.

button in cell can not respond to the onPress event in time

Pull down the data, some components are mounting,some components are unmounting, this time the button in cell can not respond to the onPress event in time, because android phone performance is not good, so the problem is more obvious

onEndReached call multiple times & not correct

Hi there, you library is very cool except onEndReached not working correctly. I know you guys will fix it in the future. My question is when you will develop it. I really really need onEndReached feature. So any suggestion? Appreciated it!

I am always getting a white screen

I am using the same code as in the example and I am getting a white screen, all the items are mounted but I am getting a just white screen with scrolling.
simulator screen shot - iphone 6s - 2018-03-30 at 16 41 05

Flickering when appending more items in data array during lazy loading

First off, thank you so much for, what in my opinion is the best and most feature-rich masonry package for RN out there today!

I came across a potential bug while attempting to do "lazy loading" with react-native-masonry-list. Once onEndReached executes, I do a fetch to the server to grab additional items, and append those items to the data array. Everything works but items already in the view begin flickering.

ezgif-1-2c48561e6d

I did some digging and modified react-native-masonry-list by adding a shouldComponentUpdate with a deep comparison of props and state. I noticed that the flickering completely stops when I do this, but this in itself is probably not a viable solution because it breaks the "pull to refresh" feature. I'm not familiar enough with the package to suggest a fix, but thought I'd share these findings.

Here is my implementation:

        <MasonryList
          contentContainerStyle={{ paddingHorizontal: 8 }}
          numColumns={2}
          data={listings}
          renderItem={({ item }) => <Listing listing={item} />}
          getHeightForItem={({ item }: *) => item.imageHeight + 40}
          refreshing={this.props.loading && !refreshDisabled}
          onRefresh={refreshDisabled ? null : onRefresh}
          onEndReached={onLoadMore}
        />

Here's the onLoadMore method. A lot of redux going on here so it may seem a little cryptic. I have tried using local state and setState instead of actions.setBrowseState to ensure that my redux actions/state isn't the culprit. I still ran into the same flickering issue.

  onLoadMore = async (): $await<void> => {
    const { actions }: * = this.props;
    const { loadingMore, offset }: * = this.props.browseState;

    if (loadingMore) {
      return;
    }

    await actions.setBrowseState({ loadingMore: true });

    try {
      // Increase the current offset
      const newOffset: number = offset + 20;

      // GraphQL query to retrieve more listings
      const { data: { browse } }: * = await this.feedRef.props.data.fetchMore({
        variables: {
          ...this.feedRef.props.browseQueryVariables,
          offset: newOffset
        },
        updateQuery: (prev: *, { fetchMoreResult }: *): BrowseQuery => {
          if (!fetchMoreResult) {
            return prev;
          }

          return immutabilityHelper(prev, {
            browse: {
              $set: [
                ...prev.browse,
                ...fetchMoreResult.browse
              ]
            }
          });
        }
      });

      actions.setBrowseState({
        loadingMore: false,
        offset: browse.length < 20 ? newOffset + browse.length : newOffset
      });
    } catch (e) {
      actions.openErrorModal(e);
    }
  };

Any thoughts would be greatly appreciated. Thanks!

Items won't be displayed until scroll. Performance issue.

Hi. As mentioned on title, items won't be show until I scroll the list a little bit. I looked into this discussion (facebook/react-native#13316) & checked that you already implemented they solution by set removeClippedSubviews={false} . Also the list will cause crashes when load many items (contain text & image).

So, is it buggy or incorrect implementation? Any plans to update the lib?

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.