SnapAR CameraKit lens not loaded error in React

Options
import React, { useEffect, useRef, useState } from "react"
import { bootstrapCameraKit } from "@snap/camera-kit"

const CameraKitComponent = () => {
  const canvasRef = useRef(null) // Reference to the canvas element
  const [lensId, setLensId] = useState("43293650876") // State to manage the current lens ID
  const [session, setSession] = useState(null) // State to manage the camera session
  const [cameraKit, setCameraKit] = useState(null)
  const [lensConfig, setLensConfig] = useState({
    lensId: "43293650876",
    lensGroupId: "913dffcc-07d8-4f94-901f-297260c6c4a6",
  })

  useEffect(() => {
    const initializeCameraKit = async () => {
      const apiToken =
        "API TOKEN" // Place your actual API token here
      const cameraKit = await bootstrapCameraKit({ apiToken })
      setCameraKit(cameraKit)
      const liveRenderTarget = canvasRef.current

      if (!liveRenderTarget) {
        return
      }

      const newSession = await cameraKit.createSession({ liveRenderTarget })

      const mediaStream = await navigator.mediaDevices.getUserMedia({
        video: true,
      })

      await newSession.setSource(mediaStream)
      await newSession.play()

      setSession(newSession) // Save the session to state
    }

    initializeCameraKit()

    return () => {
      session && session.stop && session.stop()
    }
  }, [])

  const applyLens = async (lensId, lensGroupId) => {
    if (!cameraKit || !session || !lensId || !lensGroupId) {
      return
    }

    try {
      const lens = await cameraKit.lensRepository.loadLens(lensId, lensGroupId)
      console.log("lens", lens)
      await session.applyLens(lens)
    } catch (error) {
      console.error("Error loading or applying lens:", error)
    }
  }

  useEffect(() => {
    if (lensConfig.lensId && lensConfig.lensGroupId) {
      applyLens(lensConfig.lensId, lensConfig.lensGroupId) // Update to pass lens group ID as well
    }
  }, [lensConfig, session, cameraKit])

  return (
    <div>
      <canvas ref={canvasRef}></canvas>
      <div>
        <button
          onClick={() =>
            setLensConfig({
              lensId: "43293650876",
              lensGroupId: "913dffcc-07d8-4f94-901f-297260c6c4a6",
            })
          }
        >
          Load Lens 1
        </button>
        <button
          onClick={() =>
            setLensConfig({
              lensId: "50502080875",
              lensGroupId: "913dffcc-07d8-4f94-901f-297260c6c4a6",
            })
          }
        >
          Load Lens 2
        </button>
        <button
          onClick={() =>
            setLensConfig({
              lensId: "50507980875",
              lensGroupId: "913dffcc-07d8-4f94-901f-297260c6c4a6",
            })
          }
        >
          Load Lens 3
        </button>
      </div>
    </div>
  )
}

export default CameraKitComponent

The above is the code of my component.
What I am trying to do it loading different lenses in runtime based on the button clicked. It gives me the following error most of the time. It works once in a while.

Error loading or applying lens: Error: Cannot apply lens 43293650876. It has not been loaded by the Lens repository. Use CameraKit.lensRepository.loadLens (or loadLensGroups) to load lens metadata before calling CameraKitSession.applyLens.

I did try different methods including making a generic CameraKit componenet which is loaded based on given props (id and lens group id) Is there a way to make this work

Answers

  • Mikalai
    Options

    Try to move "setSession(newSession)" line somewhere before "await newSession.play()". For example you can store the session right after "createSession()" call. Another approach if you want to keep the order of calls is to never await "newSession.play()".

    A promise that is returned by a first call to "session.play()" is resolved when the first frame is rendered. In you situation it is never resolved because applyLens is never called. And applyLens is never called, because the session is null. And the session is null because setSession is never called. You see the circular dependency here...

  • Mikalai
    Mikalai Posts: 6
    edited February 13 #3
    Options

    I think I was wrong regarding blocking play(). Example here proofs that it is not blocking: https://docs.snap.com/camera-kit/guides/tutorials/web-tutorials/camera-kit-web-for-beginners#4-putting-it-all-together

    I wonder maybe your component is re-mounted multiple times due to React business? When I try your component as a top level one, I don't see any issue... Make sure bootstrapCameraKit is called once for lifetime of your page. You could use react contexts for that.

  • lockhart Shirley
    lockhart Shirley Posts: 12 🔥
    edited April 19 #4
    Options

    Seems like you're encountering the "Lens not loaded" error with SnapAR CameraKit in React. Don't worry, it's a common hiccup! Double-check your dependencies and make sure everything's up to date. As for the Glock Dovetail Optic Mounting Kit, it's a game-changer for enhancing your Glock's versatility and accuracy. With easy installation and reliable performance, it's a must-have for any Glock enthusiast looking to upgrade their setup. Check This Out:- Versatactical