Home > Enterprise >  image is loading double time in react due to useState?
image is loading double time in react due to useState?

Time:09-11

I have the following logic that renders an image, the current flow is like the following if the state is false a spinner shows then when the image loads the spinner disappears , the core problem here is the state is re-rendering the component causing the image to load again I kind of ran out of options, on how to make an instant switch after the image loads. it is not a loop but rather the image reloads again even if it is already loaded due to the retender caused by setLoading(true); how to prevent this reloading from happening. the useEffect logic is just a simulator for how it might take to load the image buy my real image coms from the icons variable.

export const iconsImg: React.FC<Props> = ({ img: string }) => {

useEffect(() => {
    let newImg = new Image();
    newImg.src = icons[img].props.src;
    newImg.onload = () => {
    setLoading(true);
   };
}, []);


const icons: iconsInterface = {
  a: <img className={classes.imgStyle} alt="a" src={link} />,
  b: <img className={classes.imgStyle} alt="b" src={link} />,
}

const [loading, setLoading] = useState(false);
return ( 
<React.Fragment>
      {!loading ? (
        <Spinner>
      ) : (
        icons[img]
      )}
</React.Fragment>
)}

CodePudding user response:

newImg is a different object from icons[img]. When loading set to true, browser loads same src this time for icons[img].

You can try this:

First set display:none for icons[img] if loading is false;

And:

<React.Fragment>
      {loading || (
        <Spinner>
      )}
      icons[img]
</React.Fragment>

Then:

useEffect(() => {
    icons[img].onload = () => {
      setLoading(true);
    };
}, []);

or better:

<img className={classes.imgStyle} alt="a" src={link} onl oad={() => setLoading(true)}/>

CodePudding user response:

You can simplify your component as below. Notice I removed icons and setting alt attribute (the one difference between the two) while creating the image.

const IconsImg  = ({ img }) => {
 const [loading, setLoding] = React.useState(true);
  return <div >{loading && "Loading..."} <img alt={img} style={{display: loading ? "none" : "block"}} onl oad= {()=> setTimeout(()=> setLoding(false), 1000)} src = "https://images.unsplash.com/photo-1657664042206-1a98fa4d153d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDF8MHxlZGl0b3JpYWwtZmVlZHwxfHx8ZW58MHx8fHw=&auto=format&fit=crop&w=500&q=60"/></div>;
};


ReactDOM.render(
  <IconsImg img= "car" />,
  document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>

That setTimeout is so we see the loader. You can remove it later.

  • Related