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

List component to iterate over data object, not array #13905

Closed
annelorraineuy opened this issue May 10, 2017 · 2 comments
Closed

List component to iterate over data object, not array #13905

annelorraineuy opened this issue May 10, 2017 · 2 comments
Labels
Resolution: Locked This issue was locked by the bot.

Comments

@annelorraineuy
Copy link

Description

I posted on StackOverflow but no luck. Before, I used ListView successfully to iterate over a data object. Now, FlatList only accepts an array of objects, and based on the docs it says VirtualizedList can be used for any data type.

However, there's no example of overriding getItem, getItemCount, and keyExtractor for iterating over an object with keys.

Reproduction Steps and Sample Code

So far, this is what I have but it is not quite right.

import React, { Component } from 'react';
import { VirtualizedList } from 'react-native';
import _isEqual from 'lodash/isEqual';
import _size from 'lodash/size';
import _forEach from 'lodash/forEach';
import GameListView from './GameListView';

export default class GameCategoriesRoll extends Component
{
    constructor(props)
    {
        super(props)
        // console.log('data:', this.props.data);
        this._getItem = this._getItem.bind(this)
        this._keyExtractor = this._keyExtractor.bind(this)
        this._renderRow = this._renderRow.bind(this)
    }

    shouldComponentUpdate(nextProps, nextState, nextContext)
    {
        return !_isEqual(this.props, nextProps) || !_isEqual(this.state, nextState)
    }

    _keyExtractor(data) {
       // returns all keys in object
        return _forEach(data, function(category, key){
            console.log('keyextractor:', key);
            return key
        });
    }

    _getItem(data) {
      // data is the whole collection returned so i try to return just one key
        return _forEach(data, function(category, key){
            console.log('getItem category: ', category, 'key', key);
            return category
        });
    }

    _renderRow(item)
    {
        console.log('renderRow: ', item); // <- returns whole collection / object
        if (item.appItems && item.appItems.length > 0)
        {
            console.log('item', item);
            /*return (
                <GameListView
                    category={item.name}
                    games={item}
                    recentlyPlayed={false}
                />)*/
        }
    }

    render()
    {
        return (
            <VirtualizedList
                keyExtractor={(item) => this._keyExtractor(item)}
                data={this.props.data}
                getItem={(data) => this._getItem(data)}
                getItemCount={(data) => data ? _size(data) : 0}
                renderItem={this._renderRow}
                debug
                contentContainerStyle={{ flexGrow: 1, overflow: 'hidden' }}
                showsVerticalScrollIndicator={false}
                automaticallyAdjustContentInsets={false}
                removeClippedSubviews={false}
                enableEmptySections={true}
            />
        )
    }
}

Data format:

{ 
 under5: {
   categoryTitle: "5 and Under",
   items: [
      { ... },
      { ... }
    ]
  },
 learning: Object (same format as above...), 
 puzzles: Object, 
 family: Object, 
 sports: Object
...
}

Solution

Maybe an example of using VirtualizedList to iterate over complex data objects, or even a simple data object. Currently there is no example on the docs. See: https://facebook.github.io/react-native/docs/virtualizedlist.html

Additional Information

  • React Native version: 0.43.4
  • Platform: testing on Android
  • Development Operating System: macOS Sierra 10.12.4
  • Dev tools: Android Studio
@annelorraineuy
Copy link
Author

I got around it. I converted the data object to an array by using lodash's _values() https://lodash.com/docs/4.17.4#values

So this does the trick:

<FlatList
    keyExtractor={(item) => item.name}
    data={_values(this.props.data)}
    renderItem={this._renderRow}
    contentContainerStyle={{ flexGrow: 1, overflow: 'hidden' }}
    showsVerticalScrollIndicator={false}
    automaticallyAdjustContentInsets={false}
    removeClippedSubviews={false}
    enableEmptySections={true}
/>

@sahrens
Copy link
Contributor

sahrens commented May 15, 2017

I think the original problem you were having is that getItem takes both data and an index, so you need to provide a function that will take your data object and a numeric index and return the item at that index.

This can be done with a secondary index into the object, like data[keys[index]], but converting to an array is a fine solution as well if your object isn't gigantic.

@sahrens sahrens closed this as completed May 15, 2017
@facebook facebook locked as resolved and limited conversation to collaborators May 24, 2018
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Jul 18, 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

3 participants