nandorojo/moti

How to use <Skeleton> with Flatlist?

ansh opened this issue · 6 comments

ansh commented

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

Right now, if you have a FlatList, and wrap the whole thing with a Skeleton, the loader shows one small square since the FlatList data has not yet bee fulfilled.

However, if you wrap individual items (inside renderItem) with Skeleton, it doesn't work as the data is not loaded so the FlatList shows the empty component while loading is happening.

Expected Behavior

A simple way to wrap a FlatList renderItem or whole FlatList and have Skeleton loading.

Steps To Reproduce

No response

Versions

- Moti: 0.21.1
- Reanimated: 2.12.0
- React Native: 0.70.5
- Expo SDk: v47

Screenshots

No response

Reproduction

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

import { Skeleton } from "@motify/skeleton";


const LOADED_DATA = [
  {
    name: "Person 1",
    friends: "54"
  },
    {
    name: "Person 2",
    friends: "21"
  },
    {
    name: "Person 3",
    friends: "53"
  },
    {
    name: "Person 4",
    friends: "78"
  },
    {
    name: "Person 5",
    friends: "12"
  }
]
export default function App() {
  const [data, setData] = React.useState([]);

  React.useEffect(() => {
    setTimeout(() => {
      setData(LOADED_DATA);
    }, 2000)
  }, [])



  return (
    <View style={styles.container}>
      <Skeleton>
      {!!data ? <FlatList
        data={data}
        renderItem={({item, index}) => {
          return (
            <View style={{flexDirection: "row", justifyContent: "space-between", marginVertical: 20}}>
            <Text>{item.name}</Text>
            <Text>{item.friends}</Text>
            </View>
          )
        }}
        ListEmptyComponent={<Text>This list is empty!</Text>}
       /> : null}
       </Skeleton>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
});

This is expected behavior. Check out my article about skeletons and how to use them with lists:

https://dev.to/nandotherojo/stop-using-loading-spinners-pkh

ansh commented

The example that you gave in the article will work if the component is defined to handle the loading state. In my case, the renderItem lives inside the same file as the FlatList, allowing such a structure to not be possible as I cannot call that component. I guess I can refactor my code and I understand that solving for every use-case might be outside the scope of this library.

Thanks! I'll close this now.

It would be pretty easy to use with FlatList too. The article gives the idea you’d need. You could just render a different FlatList if data is undefined with an array of numbers as its data prop.

ansh commented

Yes, that is what I am doing. Definitely more code than your original example so was hoping for something like that, but this is amazing too. ;)

You could also just use my loading example without a flatlist for the loading state. It isn’t necessary to scroll a skeleton.

ansh commented

Yes, both work! Thank you :) However, now I am facing another issue #251