Same URL + user activity that updates data = update (not turn off) next/image cache values for same URL.
When the user uploads a new profile image I want to replace their previous image without having to use an entirely new URL. I tried using a cache busting query param and setting a timer to give Cloudinary time to process the upload before refreshing the component but then realized that next/image built in caching functionality is getting in the way.
In the following code, newPhoto is a boolean prop that I want to use to conditionally update the cache values by checking the current value of the actual src endpoint rather than just referring to it’s associated caches.
The noCloudinaryImage state is used to render a fallback image instead of alt text if the cloudinary src doesn’t point to an image.
The userId props is used to specify which Cloudinary image should be retrieved.
The cache buster was an attempt to only override the cache when the user uploads a new image instead of always overriding cache but it doesn’t work as a standalone.
import Link from "next/link";
import Image from "next/image";
import { useState, useEffect } from "react";
export default function ProfilePhoto(props) {
const [noCloudinaryImage, setNoClouidnaryImage] = useState(false);
const [cacheBuster, setCacheBuster] = useState('originalValue');
const userId = props.userId;
const newPhoto = props.newPhoto;
const resetNewPhotoState = props.resetNewPhotoState;
// The cloudinary url will be attempted again when the user successfully uploads a new image. To prevent an infinite loop in cases where image is uploaded but error is thrown during retrieval, I reset the newPhoto state back to initial. I don't reset to initial in the parent component because it would have potential to reset back to default before child has chance to register prop change. Resetting back to initial state is also good for case where user decides they don't like the uploaded photo and upload a new photo before component re-renders (and by default returns to initial state values).
useEffect(() => {
if (newPhoto) {
setNoClouidnaryImage(false);
resetNewPhotoState();
setCacheBuster('updateCache');
}
}, [newPhoto, resetNewPhotoState]);
//If the user isn't authenticated, the instance of this component that is used for the navbar will navigate user to create account page because there isn't a profile page associated with an unknown identity.
let profilePagePath = props.profilePagePath
? `/profile/${props.profilePagePath}`
: "/create-account-login";
let photoSrc = `${process.env.NEXT_PUBLIC_CLOUDINARY_PROFILE_IMAGE_BASE_URL}${userId}?updateCache=${cacheBuster}`;
return (
<Link href={profilePagePath}>
{!noCloudinaryImage && (
<Image
width={props.photoStyle.width}
height={props.photoStyle.height}
style={{ borderRadius: "50%" }}
src={photoSrc}
onError={() => {
setNoClouidnaryImage(true);
}}
alt="Profile Photo"
/>
)}
{noCloudinaryImage && (
<Image
width={props.photoStyle.width}
height={props.photoStyle.height}
style={{ borderRadius: "50%" }}
src={"/profile-photo/default-profile-photo.jpg"}
alt="Profile Photo"
/>
)}
</Link>
);
}
I attempted a cache busting query param. I attempted setting a timeout between upload and re-render. I did some research and found that next/image caching can be turned off but didn’t see a solution for just updating it’s value based on user interaction.
I expect that I may need to store completely new and unique URLs in my MongoDB user document and replace that url anytime the user updates their profile image. But I’d like avoid the overhead and code complexity of that approach if I can.