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