I am Using FireBase as a Database in a react-native app using Redux. I want to Show an Activity Indicator until the data is been fetched. my Redux action is:
export const fetchproducts=()=>{
return async dispatch=>{
const items = []
const db = firebase.firestore();
db.collection("Shops").collection('products').get().then((querySnapshot)=> {
querySnapshot.forEach((doc,i)=> {
items.push(new Product(
doc.id,
doc.data().name,
doc.data().description,
doc.data().price,
))
});
dispatch({
type:SET_PRODUCTS,
products:items
})
}).catch((err)=>{
throw err
})
}
}
My React Native js code is:
const ProductsOverviewScreen = props => {
const [isLoading,setIsLoading]=useState(false)
const [isRefreshing,setIsRefreshing]=useState(false)
const allshops = useSelector(state => state.shops.allshops);
const [error,setError]=useState()
const products = useSelector(state => state.products.availableProducts);
const dispatch = useDispatch();
const loadProducts=useCallback( async ()=>{
setError(null)
setIsLoading(true)
try{
await dispatch(productActons.fetchproducts())
}catch(err){
setError(err.message)
}
setIsLoading(false)
},[dispatch,setIsLoading,setError])
useEffect(()=>{
const willFocusSub=props.navigation.addListener('willFocus',()=>{
loadProducts()
})
return ()=>{
willFocusSub.remove()
}
},[loadProducts])
useEffect(()=>{
loadProducts()
},[dispatch,loadProducts])
if(error)
{
return <View style={{flex:1,alignItems:'center',justifyContent:'center'}}>
<Text>An error Occured </Text>
<Button title="Try Again" onPress={loadProducts} color={Colors.primary}></Button>
</View>
}
if(isLoading){
return <View style={{flex:1,alignItems:'center',justifyContent:'center'}}>
<ActivityIndicator size="large" color={Colors.primary}/>
</View>
}
if(!isLoading&&products.length===0)
{
return <View style={{flex:1,alignItems:'center',justifyContent:'center'}}>
<Text>No Products</Text></View>
}
return (
<View>
<FlatList
horizontal={true}
data={products}
keyExtractor={item => item.id}
renderItem={itemData => (
<ProductItem
image={itemData.item.id}
title={itemData.item.name}
price={itemData.item.price}
onSelect={() => {
selectItemHandler(itemData.item.id, itemData.item.title);
}}
>
</ProductItem>
)}
/>
</View>
The out put shows 'No Products' First and then shows the product,instead of showing the activity indicator and shows the products
Change
if(isLoading){
return <View style={{flex:1,alignItems:'center',justifyContent:'center'}}>
<ActivityIndicator size="large" color={Colors.primary}/>
</View>
}
if(!isLoading&&products.length===0)
{
return <View style={{flex:1,alignItems:'center',justifyContent:'center'}}>
<Text>No Products</Text></View>
}
to
if(!isLoading && products.length===0){
return <View style={{flex:1,alignItems:'center',justifyContent:'center'}}>
<ActivityIndicator size="large" color={Colors.primary}/>
</View>
}
if(isLoading&&products.length===0)
{
return <View style={{flex:1,alignItems:'center',justifyContent:'center'}}>
<Text>No Products</Text></View>
}
Hope this helps!