EDIT --- SOLVED
Finally figured it out. The forEach loop is not asynchronous, I replaced it with a traditional loop and that solved my issue !
export const listImagesSagafied = async (listRef) => {
const list = await listRef.listAll(); const listItems = list.items; const imgList = [];
for (let i = 0; i < list.items.length; i++) {
const galleryImage = {}
const downloadUrl = await listItems[i].getDownloadURL()
galleryImage.name = listItems[i].name
galleryImage.url = downloadUrl
imgList.push(galleryImage)
}
return imgList;
};
ORIGINAL QUESTION BELOW
Goal: Fetch image urls from firebase storage, and list them in the "Gallery" page when the gallery page is opened.
Issue: Clicking Gallery results in a blank page, but clicking it once more will render the images. Clicking on contact and then back to gallery will again render a blank page in gallery . Video https://vimeo.com/583902534
Question: How can I make it so the gallery images render upon clicking on the "Gallery" nav button ?
Code below, I tried to make it as concise as possible without leaving out any code relevant to the issue.
GALLERY COMPONENT
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { fetchGalleryStart } from '../../redux/gallery/gallery.actions';
import './gallery.styles.css';
const Gallery = () => {
const dispatch = useDispatch();
const gallery = useSelector(state => state.gallery.galleryImages);
useEffect(() => {
dispatch(fetchGalleryStart('test-images'))
}, [])
return (
<div>
<div className='page center-page'>
{<h1>Gallery Length: {gallery.length}</h1>}
{gallery &&
gallery.map((img) => (
<div key={img.name} className='gallery-image-container'>
<img src={img.url} alt={img.name}></img>
</div>
))
}
</div>
</div>
)
}
REDUX ACTIONS
import GalleryActionTypes from './gallery.types';
export const fetchGalleryStart = (storageRef) => ({
type: GalleryActionTypes.FETCH_GALLERY_START,
payload: storageRef,
})
export const fetchGallerySuccess = (galleryItems) => ({
type: GalleryActionTypes.FETCH_GALLERY_SUCCESS,
payload: galleryItems,
})
export const fetchGalleryFailure = (error) => ({
type: GalleryActionTypes.FETCH_GALLERY_FAILURE,
payload: error,
})
REDUX REDUCER
import GalleryActionTypes from './gallery.types';
const INITIAL_STATE = {
galleryImages: null,
isFetching: false,
error: null,
}
const galleryReducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case GalleryActionTypes.FETCH_GALLERY_START:
return {
...state,
isFetching: true,
}
case GalleryActionTypes.FETCH_GALLERY_SUCCESS:
return {
...state,
isFetching: false,
galleryImages: action.payload,
}
case GalleryActionTypes.FETCH_GALLERY_FAILURE:
return {
...state,
isFetching: false,
error: action.payload,
}
default: return state;
}
};
export default galleryReducer;
REDUX SAGAS
import { put, takeLatest, call, all } from 'redux-saga/effects';
import GalleryActionTypes from './gallery.types';
import { fetchGallerySuccess, fetchGalleryFailure } from './gallery.actions';
import { firestorage, listImagesSagafied } from '../../firebase/firebase-utils';
function* getGalleryItems({ payload }) {
try {
const storageRef = firestorage.ref();
const listRef = yield storageRef.child(payload);
const images = yield call(listImagesSagafied, listRef)
yield put(fetchGallerySuccess(images));
} catch (error) {
yield put(fetchGalleryFailure(error));
}
};
export function* fetchGalleryItemsStart() {
yield takeLatest(GalleryActionTypes.FETCH_GALLERY_START, getGalleryItems);
};
export function* gallerySagas() {
yield all([
call(fetchGalleryItemsStart),
])
};
FIREBASE FUNCTION FOR FETCHING STORAGE ITEMS
export const listImagesSagafied = (listRef) => {
const imgList = []
listRef.listAll()
.then((res) => {
res.items.forEach((itemRef) => {
const shopItem = {};
shopItem.name = itemRef.name;
itemRef.getDownloadURL()
.then((url) => {
shopItem.url = url
imgList.push(shopItem)
})
});
})
.catch((error) => { console.log(error) });
return imgList;
};