У меня есть изображение, которое я беру из конечной точки API. По какой-то причине я импортирую компонент изображения внутри Suspense с запасным вариантом. Проблема в том, что каждый раз, когда выполняется useState или useEffect, отображается запасной вариант Suspense. Есть ли способ предотвратить отображение резервного варианта Suspense после первого рендеринга или при кэшировании изображения?
export async function AvatarIcon({ id }: { id: string }) {
const avatarIcon = await getAvatarIcon(id)
return (
<div className = "">
<Image
src = {`data:image/png;base64, ${avatarIcon}`}
height = {40}
width = {40}
className = "relative z-0 h-full w-16"
alt = "Avatar Icon"
></Image>
</div>
)
}
Другой компонент, который я использую Suspense:
<div>
<Suspense fallback = {<div></div>}>
<AvatarIcon id = {user.id} />
</Suspense>
</div>
Да, я использую nextJs. Есть ли другой способ сделать это?
И просто убедиться, что файл AvatarIcon нигде не делает use client?





fallback работает, потому что значение свойства loading по умолчанию — «ленивый». из документов
Поведение загрузки изображения. По умолчанию ленивый.
Если вам лень, отложите загрузку изображения до тех пор, пока оно не достигнет расчетного значения. расстояние от видового экрана.
Когда захотите, немедленно загрузите изображение.
если вы измените loading = "eager", это может сработать (я не проверял), потому что компонент уже загружен и готов к рендерингу. Компонент Suspense показывает свое резервное содержимое только тогда, когда обернутый компонент не готов к рендерингу.
Но я думаю, что установка «жаждущего» параметра внутри Suspense не имеет смысла, поскольку Suspense специально разработан для обработки компонентов, загружающихся асинхронно.
поскольку вы извлекаете изображение, возможно, вам следует кэшировать эту выборку с помощью useSwr или нестабильного_кэша
поскольку вы получаете изображение из API, в next.js есть опция файла загрузчика. например, для облачности
// Демо: https://res.cloudinary.com/demo/image/upload/w_300,c_limit,q_auto/turtles.jpg
экспортировать функцию по умолчанию cloudinaryLoader({ src, width,quality }) {
const params = ['f_auto', 'c_limit', w_${width}, q_${quality || 'auto'}]
вернись https://example.com/${params.join(',')}${src}
}
в этом файле загрузчика вы можете проверить Поведение кэширования :
Ниже описан алгоритм кэширования для загрузчика по умолчанию. По всем остальным загрузчикам обращайтесь к поставщику облачных услуг. документация.
Изображения оптимизируются динамически по запросу и сохраняются в Каталог /cache/images. Оптимизированный файл изображения будет подается для последующих запросов до истечения срока действия. Когда сделан запрос, который соответствует кэшированному файлу, но срок действия которого истек, срок действия файла с истекшим сроком действия изображение сразу становится устаревшим. Затем изображение снова оптимизируется в фоновом режиме (также называемая повторной проверкой) и сохраняется в кеше с новым сроком годности.
Статус кэша изображения можно определить, прочитав значение заголовок ответа x-nextjs-cache. Возможные значения: следующий:
- MISS - пути нет в кеше (происходит максимум один раз, при первом посещении)
- УСТАРЕВШИЙ — путь находится в кеше, но время повторной проверки превысило время, поэтому он будет обновлен в фоновом режиме.
- HIT — путь находится в кеше и не превысил время повторной проверки. Срок действия (или, скорее, максимальный возраст) определяется либо параметром конфигурация минимальногоCacheTTL или исходный образ Cache-Control заголовок, в зависимости от того, какой из них больше. В частности, значение максимального возраста Используется заголовок Cache-Control. Если найдены оба s-maxage и max-age, тогда предпочтительнее s-maxage. Максимальный возраст также передается на любой последующие клиенты, включая CDN и браузеры.
Вы можете настроить
minimumCacheTTL, чтобы увеличить продолжительность кэша. когда восходящий образ не включает заголовок Cache-Control или значение очень низкое. Вы можете настроить размер устройств и размер изображений для уменьшить общее количество возможных генерируемых изображений. Ты можешь настроить форматы, чтобы отключить несколько форматов в пользу одного формат изображения.
Большое спасибо за подробный ответ. Нетерпеливый вариант и нестабильный кэш не сработали. Однако useSwr делает свою работу. Теперь все работает правильно.
const fetcher = (url: string, id: string) => {
const urlWithQuery = ${url}/${id}/icon
return fetch(urlWithQuery).then((res) => res.json())
}
const { data, error, isLoading } = useSWR(
['/api/avatar', id],
([url, id]) => fetcher(url, id),
{
revalidateOnFocus: true
}
)
Используете ли вы компоненты React Server или построенную на нем платформу? Я думаю, да, поскольку ваш пример полностью взорвется на клиентском компоненте, поскольку компоненты там не могут быть асинхронными.