Search code examples
react-nativeasync-awaitreact-native-flatlist

React-Native: How to use async functions to get data for flatlist


I'm pretty new to react native, and have been working on a timesheets app recently. I'm trying to get data from a database and display it in a flatlist, however the flatlist keeps appearing empty. I'm not really sure I'm doing wrong. When I log the data to the console it logs the correct data to the console but when I try to make the flatlist render the data it appears empty

timesheets.js

export default function TimesheetScreen({ navigation }) {
      
      const getData = async () => {
        data = await getTimesheets()
        console.log(data);
        return data;
      }

      const timesheetsData = getData();
      
      const Item = ({ name }) => (
        <View style={styles.body}>
          <Text styles={styles.bodyText}>{name}</Text>
        </View>
      );
        
       const renderItem = ({ item }) => (
        <TouchableOpacity onPress={() =>navigation.navigate('DetailScreen', item)}>
          <Item name={item.name +": " + item.date}/>
        </TouchableOpacity>
      );

            return (
              <View style={styles.container}>
                <View style={styles.header}>
                  <Text style={styles.headerText}>My Timesheets</Text>
                  
                </View>
                <TextInput 
                  style={styles.searchBackground}
                  placeholder='Enter Employee Name'
                  onEndEditing={text=>console.log(text)}/>
                <FlatList
                data={timesheetsData}
                renderItem={renderItem}
                keyExtractor={item => item.clockID}
                />
              </View>
            );
          }
    

the function that is querying the database

export const getTimesheets = async () =>{
      //gets all employee records from collection employees
    var allTimesheets= await firebase.firestore()
    .collection('employees')
    .get();
    var timesheetsArray=[];
    for(let i=0;i<(allTimesheets.docs).length;i++){
        let timesheetsData=(allTimesheets.docs[i]).data();
       timesheetsArray.push(timesheetsData);
 
    }

Thank You


Solution

  • I have noticed that you are missing state. In React, every time state is changed makes UI re-render with new state data.

    After getting database result, you have to re-render screen with state variable. This can be solved by React.useState() hook function.

    So, please try this way.

     export default function TimesheetScreen({ navigation }) {
              
              const getData = async () => {
                data = await getTimesheets()
                console.log(data);
                return data;
              }
    
              const [data, setData] = React.useState([]);
        
              
    
              React.useEffect(async () => {
                  const timesheetsData = await getData();
                  setData(timesheetsData);
              });
              
              const Item = ({ name }) => (
                <View style={styles.body}>
                  <Text styles={styles.bodyText}>{name}</Text>
                </View>
              );
                
               const renderItem = ({ item }) => (
                <TouchableOpacity onPress={() =>navigation.navigate('DetailScreen', item)}>
                  <Item name={item.name +": " + item.date}/>
                </TouchableOpacity>
              );
        
              return (
                <View style={styles.container}>
                  <View style={styles.header}>
                    <Text style={styles.headerText}>My Timesheets</Text>
        
                  </View>
                  <TextInput 
                    style={styles.searchBackground}
                    placeholder='Enter Employee Name'
                    onEndEditing={text=>console.log(text)}/>
                  <FlatList
                  data={data}
                  renderItem={renderItem}
                  keyExtractor={item => item.clockID}
                  />
                </View>
              );
     }