Reputation: 2705
I have a React app that receives a stream of image URIs from an EventSource
. I want to display the most recent image, and only replace the image once the next image is fully loaded and can be displayed instantaneously. How do I accomplish this?
Edit 2: My current implementation does exactly this, except for one critical component: the most recent image is displayed as it loads, changing the vertical arrangement of the page.
Edit: Adding relevant snippets of code, this is my EventSource
:
useEffect(() => {
let serverImageURIsEventSource = new EventSource(
url,
{withCredentials: false})
serverImageURIsEventSource.addEventListener('open', () => {
console.log('SSE opened!');
});
serverImageURIsEventSource.addEventListener('message', (e) => {
console.log(e.data);
setImageURIs([e.data]); // e.data is a string to the image URI
});
serverImageURIsEventSource.addEventListener('error', (e) => {
console.error('Error: ', e);
});
serverImageURIsEventSource.addEventListener('close', () => {
console.log('SSE closed!');
serverImageURIsEventSource.close();
});
return () => {
serverImageURIsEventSource.close();
};
}, [prompt]);
And this is my JSX with the images.
<ImageList cols={1}>
{imageURIs.map((imageURI) => (
<ImageListItem key={imageURI}>
<img
src={`${imageURI}`}
srcSet={`${imageURI}`}
loading="lazy"
// loading="eager" default
/>
</ImageListItem>
))}
</ImageList>
Upvotes: 0
Views: 1897
Reputation: 1120
Make imageURIs
as an array of object instead of array and a assign a number prop as your reference to order it by when you render it.
setImageURIs(prevImageUris => [...prevImageUris, {uri: e.data, number: prevImageUris.length + 1}])
and use sort
when rendering
{imageURIs.sort((a,b) => b.number - a.number).map((imageURI) => (
<ImageListItem key={imageURI.uri}>
<img
src={`${imageURI.uri}`}
srcSet={`${imageURI.uri}`}
loading="lazy"
// loading="eager" default
/>
</ImageListItem>
))}
Upvotes: 1