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

Time:03-12

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

CodePudding user response:

Since getData is async, the constant timesheetsData does not contain anything in the first render cycle and since you are not triggering a state change when the data is ready, no rerender is triggered, resulting in an empty FlatList.

This could be solved by using a useEffect and introducing a state variable as follows.

export default function TimesheetScreen({ navigation }) {

      const [timesheetsData, setTimeSheetsData] = useState()

      useEffect(() => {
         const getData = async () => {
           data = await getTimesheets()
           console.log(data);
           setTimeSheetsData(data);
         }

         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>
            );
          }

CodePudding user response:

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>
          );
 }
  • Related