title: How to conditionally render an image in React?
body: <p>Imagine that I want to create a component to render an image. If the image resource is valid, I should render it into a div via css <code>background-image</code>. Otherwise I should render it as a standard <code>&lt;img&gt;</code> with an alt tag.</p>
  
  <p>So we get something like this:</p>
  
  <pre><code>const ImageComponent = ({src}) =&gt; {
    const [loaded, setLoaded] = useState(false);
    const [renderFallback, setRenderFallback] = useState();
  
    useEffect(() =&gt; {
      const image = new Image();
      image.onsuccess = () =&gt; {
        setLoaded(true);
        setRenderFallback(false);
      }
      image.onerror = () =&gt; {
        setLoaded(true);
        setRenderFallback(true);
      }
      image.src = src;
  
      return () =&gt; {
        // clean up listeners
        image.onsuccess = undefined;
        image.onerror = undefined;
      }
    }, [src]);
  
    if (!loaded) { return null; }
  
    return renderFallback ?
      &lt;div style={{backgroundImage: `url(${src})`}}/&gt; :
      &lt;img src={src} alt="my alt"/&gt;;
  }
  </code></pre>
  
  <p>Here, we first kick off a fetch for the image via plain javascript (within useEffect). If it's valid, the resource is cached (by the browser), and the rendering of the subsequent <code>&lt;div&gt;</code> is instantaneous. </p>
  
  <p>However, if the resource is not valid, then there is no caching mechanism in place (see <a href="https://stackoverflow.com/questions/60621406/is-it-possible-to-cache-a-broken-image">this question</a> for more details). And so when we render the new <code>&lt;img&gt;</code> element at the end of the Component, it kicks off a brand new request to fetch that image (despite deducing that it's broken already).</p>
  
  <p>So, to avoid this duplicate fetching, a possible solution would be to render the already-initialized <code>image</code> element, rather than a new react element to represent that image. </p>
  
  <p>Is this possible?</p>
  
  <hr>
  
  <p><strong>Feedback from comments</strong></p>
  
  <ul>
  <li>An invalid image is one that returns a <em>status of 404</em>, or points to a resource that's <em>not actually an image</em> (e.g. <code>https://goodreads.com</code>)</li>
  <li>I would like to display the browser's default 'broken image' in cases where it's broken. This can't be done via <code>background-image</code> css, so I need to rely on a standard <code>&lt;img&gt;</code> element. As I've already determined that the image is broken (in useEffect), I'd like to avoid a new fetch when I'm rendering the broken <code>&lt;img&gt;</code> in React.</li>
  </ul>
  
  <p>Hope that clarifies things!</p>