reactjscontentfulavif

how to detect that avif is supported or not in reactjs?


I am trying to optimize the image by formatting that to avif. But some of the browser's are not supporting avif.

So I created a utility function like this

  function isAvifSupported() {
    let returnValue;
    const avif = new Image();
    avif.src =
      "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A=";
    avif.onload = function () {
        returnValue = true
    };
    return returnValue;
  }

but when I try to call this function it always returns undefined. But when I use the function that has been provided in avif site. it works fine. Below is the code for it

function AddClass(class) { document.documentElement.classList.add(class) };
var avif = new Image();
avif.src = "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A=";
avif.onload = function () { AddClass("avif") };
avif.onerror = function () {
  var webp = new Image();
  webp.src = "data:image/webp;base64,UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==";
  webp.onload = function () { AddClass("webp") }
}

But the above-defined function adds the css at the top level of dom. Instead of adding the class, It has to return true or false. So that i am able to handle that easily like this.


let updatedImageUrl = isAvifSupported() ? `${imageUrl}?fm=avif` ? imageUrl

But I don't know, how to fix this. Please recommend a solution.


Solution

  • The below functionality will work fine. It is an extended answer version of @Stefan Judis. I modified this depending upon my project

    import React, { useEffect, useState } from "react";
    import "./styles.css";
    
    const url =
      "https://images.ctfassets.net/{space_id}/1WJFyl9C8q18KI6OQG7mPu/{unique_name}/name.jpg";
    
    const ImageFormat = () => {
      const [imageFormat, setImageFormat] = useState("");
    
      function addImageProcess(src) {
        return new Promise((resolve, reject) => {
          let img = new Image();
          img.onload = () => resolve("avif");
          img.onerror = () => {
            const webp = new Image();
            webp.src =
              "data:image/webp;base64,UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==";
            webp.onload = async () => {
              resolve("webp");
            };
    
            webp.onerror = () => {
              reject("");
            };
          };
          img.src = src;
        });
      }
    
      useEffect(() => {
        async function logImageFormat(imageUrl) {
          let imageFormatValue = await addImageProcess(imageUrl);
          setImageFormat(`${url}?fm=${imageFormatValue}&w=3500`);
        }
    
        logImageFormat(
          "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A="
        );
      }, []);
    
      return (
        <>
          <div className="App">{imageFormat}</div>
        </>
      );
    };
    
    export default ImageFormat;