Rylan Schaeffer
Rylan Schaeffer

Reputation: 2705

React JS - How to update image only once loaded?

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

Answers (1)

Drew Cordano
Drew Cordano

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

Related Questions