I am actually trying to get orders as objects stored in firebase and display them in the history screen but the flatlist shows an empty screen on initial render and displays the items on refreshing again resulting in that items are displayed twice and hence causes duplicate keys?? How should I make the flatlist render things on first go??
export const HistoryScreen = () => {
const [isLoading, setIsLoading] = useState(true);
const [ list, setList] = useState([]);
var json = [];
var keys = [];
const firebaseRef = firebase.database().ref(`Orders/${orderData.firebaseUserId}`);
const getJson = async () => {
await firebaseRef.on("value" , (snapshot) => {
json = snapshot.val();
});
}
const SendingData = async () => {
await getJson();
keys = Object.keys(json);
//Mapping Data
keys.map((key) => {
let k = json[key];
let appliance = Data.find((app) => app.title === k["Appliance_Name"]);
let obj = {"id" : key, "title" : k['Appliance_Name'], "service" : k['Service_Requested'],
"time" : k['Time'], "status" : k["Status"], "image" : appliance.image};
list.push(obj);
})
}
useEffect(() => {
setTimeout(() => {
setIsLoading(false);
}, 3000);
}, []);
useEffect(() => {
SendingData();
})
return (
<SafeArea>
<LinearGradient style={styles.screen} colors={[color.screenBackground.g3, color.screenBackground.g2,color.screenBackground.g2, color.screenBackground.g3]}>
{isLoading ? (
<View style={styles.loader}>
<ActivityIndicator size="large" color={color.screenBackground.g4} />
</View>
) : (
<View style={styles.screen}>
<Appointments>Your Appointments</Appointments>
<OrderCard>
<Scroll>
<FlatList style={styles.list}
data = {list}
renderItem = { ({ item }) => (
<Item>
<View style={styles.view}>
<View>
<Image source={item.image} resizeMode='contain' style={styles.image}/>
</View>
<View style={styles.container}>
<Title>{item.title}</Title>
<Service>Job : {item.service}</Service>
<Time>Booking Time : {item.time}</Time>
<ID>Appointment ID : {item.id}</ID>
</View>
</View>
<Status>Status : {item.status}</Status>
</Item>
)}
keyExtractor = {item => item.id}
/>
</Scroll>
</OrderCard>
</View>
)}
</LinearGradient>
</SafeArea>
);
}
you need to enhance the method that you use to get data.
The first thing you need to use the setList
to add items and not list.push
.
const [isLoading, setIsLoading] = useState(true);
const [ list, setList] = useState([]);
const firebaseRef = firebase.database().ref(`Orders/${orderData.firebaseUserId}`);
const SendingData = async () => {
let data = []
let tmp_keys;
await firebaseRef.on("value" , (snapshot) => {
let json = snapshot.val();
tmp_keys = Object.keys(json);
tmp_keys.map((key) => {
let k = json[key];
let appliance = Data.find((app) => app.title === k["Appliance_Name"]);
let obj = {"id" : key, "title" : k['Appliance_Name'], "service" : k['Service_Requested'],
"time" : k['Time'], "status" : k["Status"], "image" : appliance.image};
data.push(obj)
});
setLits(data)
})
}
also the isLoading set to false can be done at the end of SendingData