title: React: Trying to achieve a sequential fade-in effect with a Masonry layout but it's out of order
body: <p>I been trying to make a Masonry gallery with a sequential fade-in effect so that the pictures fade in one by one. And there is also a shuffle feature which will randomize the images and they fade in again after being shuffled.</p>
  
  <p>here is the demo and the code:</p>
  
  <p><a href="https://tuo1t.csb.app/" rel="nofollow noreferrer">https://tuo1t.csb.app/</a></p>
  
  <p><a href="https://codesandbox.io/s/objective-swartz-tuo1t" rel="nofollow noreferrer">https://codesandbox.io/s/objective-swartz-tuo1t</a></p>
  
  <p>When first visiting the page, the animation is correct. However once we click on the shuffle button, something weird happened: There are often some pictures don't fade-in sequentially after the image before them faded in, there is even no fade-in animation on them, they just show up out of order.</p>
  
  <p>The way I achieved this animation is by adding a delay transition based on the index of the image, and use <code>ref</code> to track images.</p>
  
  <p>first I initialize the <code>ref</code></p>
  
  <pre><code> let refs = {};
    for (let i = 0; i &lt; images.length; i++) {
      refs[i] = useRef(null);
    }
  </code></pre>
  
  <p>and I render the gallery </p>
  
  <pre><code> &lt;Mansory gap={"1em"} minWidth={minWidth}&gt;
          {imgs.map((img, i) =&gt; {
            return (
              &lt;PicContainer
                index={img.index}
                selected={isSelected}
                key={img.index}
              &gt;
                &lt;Enlarger
                  src={img.url}
                  index={img.index}
                  setIsSelected={setIsSelected}
                  onLoad={() =&gt; {
                    refs[i].current.toggleOpacity(1); &lt;--- start with zero opacity images till those are loaded
                  }}
                  ref={refs[i]}
                  realIndex={i}
                /&gt;
              &lt;/PicContainer&gt;
            );
          })}
        &lt;/Mansory&gt;
  </code></pre>
  
  <p>for the every image component</p>
  
  <pre><code>class ZoomImg extends React.Component {
    state = { zoomed: false, opacity: 0 };
  
    toggleOpacity = o =&gt; {
      console.log("here");
      this.setState({ opacity: o }); &lt;-- a setter function to change the opacity state via refs:
    };
  
    render() {
      const {
        realIndex,
        index,
        src,
        enlargedSrc,
        setIsSelected,
        onLoad
      } = this.props;
      return (
        &lt;div style={{ margin: "0.25rem" }} onLoad={onLoad}&gt;
          &lt;Image
            style={{
              opacity: this.state.opacity,
              transition: "opacity 0.5s cubic-bezier(0.25,0.46,0.45,0.94)",
              transitionDelay: `${realIndex * 0.1}s` &lt;--- add a delay transition based on the index of the image.
            }}
            zoomed={this.state.zoomed}
            src={src}
            enlargedSrc={enlargedSrc}
            onClick={() =&gt; {
              this.setState({ zoomed: true });
              setIsSelected(index);
            }}
            onRequestClose={() =&gt; {
              this.setState({ zoomed: false });
              setIsSelected(null);
            }}
            renderLoading={
              &lt;div
                style={{
                  position: "absolute",
                  top: "50%",
                  color: "white",
                  left: "50%",
                  transform: "translateY(-50%} translateX(-50%)"
                }}
              &gt;
                Loading!
              &lt;/div&gt;
            }
          /&gt;
        &lt;/div&gt;
      );
    }
  }
  </code></pre>
  
  <p>I used <code>console.log("here");</code> in the setter function, which will be called for changing the opacity state via refs. There are 16 images, so initially it is called 16 times. But when I clicked on the shuffle button, you can see that it is called <strong>fewer than</strong> 16 times because some of the pictures show up directly without fading in.</p>
  
  <p>I been struggling with this problem for days and really hope someone can give me some hints.</p>