Как визуализировать JSX, возвращаемый асинхронной функцией, вызванной изнутри Array.Map() в React?

В моем приложении React я вызываю асинхронную функцию, которая отображает JSX изнутри array.map(), но ничего не отображается. Я подтвердил, что функция вызывается правильно.

Я подозреваю, что что-то связано с выполнением рендеринга до того, как асинхронная функция вернет свой результат, но я не понимаю, почему это произойдет, если асинхронная функция использует ожидание в своих внутренних вызовах.

<div>
   {
      gallery.map((image) => 
         {renderImage(image, 'vegan-mundi-gallery')}
   )}
</div>

Я попытался обернуть функцию, которая генерирует JSX, внутри фрагмента React (<></>), как показано в приведенном ниже фрагменте, но затем я получаю сообщение об ошибке «Объекты недействительны в качестве дочернего элемента React (найдено: [object Promise])». .

{
   gallery.map((image) => (
   // The react fragment below is generating the error Objects are not valid as a React child    (found: [object Promise]) - which reinforced the idea that the async function haven’t returned its result by the time of the rendering
      <>
         {renderImage(image, 'vegan-mundi-gallery')}
      </>
   )
)}

Кто-нибудь может помочь с этим?

Это мой полный код:

import { useEffect, useState } from "react";

export default function Gallery (){

    const [isLoading, setIsLoading] = useState(true);
    const [gallery, setGallery] = useState([]);

    useEffect( ()=> {
    // some code that gets the gallery array from an API call and handles the isLoading state 
    } , []);

    const renderImage = async(item, bucket) => {

        const photo = item.PHOTO;
        const data = await fetch(`http://1.1.1.1:4000/s3/${bucket}/${photo}`);
        const preSignedUrl = await data.json();
        console.info(preSignedUrl) // I can see the preSignedUrl in the console, so the async call worked!

        return (
            <figure>
                <div>
                    <img key = {photo}
                        src = {`${preSignedUrl}`}
                    />
                </div>
                <figcaption>{item.LABEL}</figcaption>
            </figure>
        )
    }


    if (isLoading){
        return(<p>loading...</p>);
    }
    else {

        return (
                <div>
                    {
                        gallery.map((image) => 
                                {renderImage(image, 'vegan-mundi-gallery')}

                    )}
                </div>
          )
    }
}

Я проверил

Я бы рекомендовал выполнять все асинхронные вызовы внутри useEffect и сохранять результаты в состоянии, чтобы избежать асинхронных вызовов при рендеринге.

JW. 23.06.2024 01:12

Спасибо, что указал мне правильное направление, JW. Я изо всех сил пытался понять, как это реализовать, а затем @Dileepa Mabulage предоставил решение!

GenerikError 23.06.2024 06:15
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
2
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Лучше используйте useEffects, чтобы справиться с этой ситуацией.

const [gallery, setGallery] = useState([]);

useEffect(() => {
        // Simulate API call to get gallery array
        const fetchGallery = async () => {
            const galleryData = [
                { PHOTO: 'photo1.jpg', LABEL: 'Label 1' },
                { PHOTO: 'photo2.jpg', LABEL: 'Label 2' },
            ];
            setGallery(galleryData);
        };

        fetchGallery();
    }, []);

для получения изображений

const [images, setImages] = useState([]);
const [isLoading, setIsLoading] = useState(true);


useEffect(() => {
        const fetchImages = async () => {
            const fetchedImages = await Promise.all(
                gallery.map(async (item) => {
                    const photo = item.PHOTO;
                    const response = await fetch(`http://1.1.1.1:4000/s3/bucketname/${photo}`);
                    const preSignedUrl = await response.json();
                    return { ...item, url: preSignedUrl };
                })
            );
            setImages(fetchedImages);
            setIsLoading(false);
        };

        if (gallery.length > 0) {
            fetchImages();
        }
    }, [gallery]);
if (isLoading) {
        return (<p>loading...</p>);
    } else {
        return (
            <div>
                {images.map((image) => (
                    <figure key = {image.PHOTO}>
                        <div>
                            <img src = {image.url} alt = {image.LABEL} />
                        </div>
                        <figcaption>{image.LABEL}</figcaption>
                    </figure>
                ))}
            </div>
        );
    }

Огромное спасибо, @Dileepa Mabulage! Я реализовал это так же, как в вашем примере, и он работает так, как я хотел. Загвоздка, которую я не смог выяснить самостоятельно, заключалась в переменной состояния галереи, вызывающей вызов асинхронной функции для генерации заранее подписанного URL-адреса. Молодец, сэр!

GenerikError 23.06.2024 06:20

Рад, что здесь это

Dileepa Mabulage 23.06.2024 08:05

Другие вопросы по теме

Похожие вопросы

Реакция: сброс группы переключателей пользовательского интерфейса материала в форме Formik не работает
Как создать универсальный крючок для извлечения данных в TypeScript для API с различными структурами ответов?
Можно ли надежно буферизовать исходящие POST-запросы из автономного React PWA?
Обертка с помощью React.StrictMode в Next.js
Как я могу создать переводчик, который конвертирует язык моего динамического сайта с английского на французский?
Использование NPM для создания приложения React: СЕРЬЕЗНОЕ ИЗМЕНЕНИЕ: webpack <5 используется для включения полифилов для основных модулей node.js по умолчанию. Это уже не так
Как смоделировать функцию внутри компонента реагирования с помощью Jest?
Как передать состояние от дочернего компонента к родительскому в Next.js?
React Query – использовать ответ от выборки списка на setQueryData для каждого элемента?
Я не могу предварительно заполнить поля ввода в моей форме. Может кто-нибудь мне помочь?