zp26
zp26

Reputation: 1527

React Native FlatList with object

I want to render object with React Native's FlatiList but this component doesn't return the expected result. My dictionary is like this:

Object {
  "Lisa.Sky": Object {
    "name": "Lisa",
    "surname": "Sky",
    "age": 21,
    "sex": female
  },  
  "Thomas.Prat": Object {
    "name": "Thomas",
    "surname": "Prat",
    "age": 33,
    "sex": male
  },  
  "Paul.Sing": Object {
    "name": "Paul",
    "surname": "Sing",
    "age": 88,
    "sex": male
  },
  "Andrew.Brown": Object {
    "name": "Andrew",
    "surname": "Brown",
    "age": 23,
    "sex": male
  },
}

I have implemented a FlatList like this, but I have white screen

   <View>
       <ScrollView>
           <FlatList
                data={this.props.nameList}
                renderItem={({item}) => 
                    <View key={item.name + "." + item.surname}>  
                        <Text style={styles.viewDetail}>{item.name}</Text>
                        <Text style={styles.viewDetail}>{item.surname}</Text>
                        <Text style={styles.viewDetail}>{item.age}</Text>
                        <Text style={styles.viewDetail}>{item.sex}</Text>
                    </View>
                }
                keyExtractor={(index) => index.toString()}
           />
       </ScrollView>
   </View>

Thanks

Upvotes: 10

Views: 20479

Answers (6)

Vikram
Vikram

Reputation: 632

I wrote following utility function to convert tree data into flat array of objects:

const isLiteralObject = (a) => {
    return !!a && a.constructor === Object;
};

/**
 * Utility to convert tree data into flat array of object to be used 
 * to render lists
 * 
 * @param obj - JSON/JS object
 * @param idField item identifier to be used as parent ID for children nodes
 * @param level - level in tree starting with 1
 * @param parent - parent ID to be set to children (extracted based on given idField)
 * @returns Array<any>
 */
const objectToFlatArray = (obj, idField = 'id', level = 0, parent = '') => {
    if (!isLiteralObject(obj)) {
        return obj;
    }

    let arr = [];

    const isValidNode = Object.values(obj).some((item) => !isLiteralObject(item));

    const nextLevel = isValidNode ? level + 1 : level;

    const nObj = { __level__: nextLevel, __parent__: parent };

    for (const k in obj) {
        if (isLiteralObject(obj[k])) {
            arr = arr.concat(
                objectToFlatArray(obj[k], idField, nextLevel, obj[idField] || parent)
            );
        } else {
            nObj[k] = obj[k];
        }
    }

    Object.keys(nObj).length > 2 && arr.unshift(nObj);

    return arr;
};

console.log(objectToFlatArray({
                    'Lisa.Sky': {
                      name: 'Lisa',
                      surname: 'Sky',
                      age: 21,
                      sex: 'female',
                    },
                    'Thomas.Prat': {
                      name: 'Thomas',
                      surname: 'Prat',
                      age: 33,
                      sex: 'male',
                    },
                    'Paul.Sing': {
                      name: 'Paul',
                      surname: 'Sing',
                      age: 88,
                      sex: 'male',
                    },
                    'Andrew.Brown': {
                      name: 'Andrew',
                      surname: 'Brown',
                      age: 23,
                      sex: 'male',
                    },
                  }))

Upvotes: 0

Sjonchhe
Sjonchhe

Reputation: 828

You can do it by

<Flatlist 
   data={Object.values(obj)}
   ...
  />

Upvotes: 4

Rasmus Knap
Rasmus Knap

Reputation: 283

I got to this old post because I googled "flatlist react native support object" and in turns out - FlatList only supports array. But the underlying VirtualizedList do support object.

My data is structured by recommendations from redux:

const data = {
    byId: {
        0: { id: '0', name: 'Bill' },
        1: { id: '1', name: 'Steve' },
        2: { id: '2', name: 'Dan' },
    },
    allIds: [0, 1, 2]
};

And i need VirtualizedList to support this data structure

<VirtualizedList
// Use keyExtractor to help the list optimize performance
    keyExtractor={item => item.id}
    data={data}
    initialNumToRender={7}
    renderItem={({item})=> {
        return <Text>{item.name}</Text>;
    }}
// the virtualized list doesn't know how you want to extract your data
// you need to tell it
    getItem={(data, index) => {
        const dataIndex = data.allIds[index];
        return data.byId[dataIndex];
    }}
// it also needs to know how much data you have
    getItemCount={data => data.allIds.length}
/>

The difference between the FlatList implementation and the VirtualizedList is just you need to overwritegetItem and getItemCount

You can see full example here: https://snack.expo.io/@rcknti/virtualized-list-example

Upvotes: 2

sdkcy
sdkcy

Reputation: 3548

You need to use your data as an array(If you need, you can check that from https://facebook.github.io/react-native/docs/flatlist#data ). Your data can be something like that,

const nameList = [
    {
        "name": "Lisa",
        "surname": "Sky",
        "age": 21,
        "sex": female
    },
    {
        "name": "Thomas",
        "surname": "Prat",
        "age": 33,
        "sex": male
    },
    {
        "name": "Paul",
        "surname": "Sing",
        "age": 88,
        "sex": male
    },
    {
        "name": "Andrew",
        "surname": "Brown",
        "age": 23,
        "sex": male
    },
];

Upvotes: 1

Nazır Dogan
Nazır Dogan

Reputation: 1588

you can do like this way. check working snack. https://snack.expo.io/@nazrdogan/bad-cashew

import * as React from 'react';
import { Text, View, StyleSheet, FlatList } from 'react-native';
import { Constants } from 'expo';

// You can import from local files
import AssetExample from './components/AssetExample';

// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
var obj = {
  'Lisa.Sky': {
    name: 'Lisa',
    surname: 'Sky',
    age: 21,
    sex: 'female',
  },
  'Thomas.Prat': {
    name: 'Thomas',
    surname: 'Prat',
    age: 33,
    sex: 'male',
  },
  'Paul.Sing': {
    name: 'Paul',
    surname: 'Sing',
    age: 88,
    sex: 'male',
  },
  'Andrew.Brown': {
    name: 'Andrew',
    surname: 'Brown',
    age: 23,
    sex: 'male',
  },
};
export default class App extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <FlatList
          data={Object.keys(obj)}
          renderItem={({ item }) => <Text>{obj[item].name}</Text>}
        />
      </View>
    );
  }
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
});

Upvotes: 34

aseferov
aseferov

Reputation: 6393

According to documentation

For simplicity, data is just a plain array. If you want to use something else, like an immutable list, use the underlying

Try to pass data as array not object

Upvotes: 2

Related Questions