Необработанный отказ (ошибка типа): Не удается установить свойство ‘innerHTML’ неопределенного

#javascript #reactjs #undefined #face-api #use-ref

Вопрос:

Я использую ReactJS для выполнения face-api-js распознавания лиц. В журнале консоли я получаю значения, но они не отображаются в видео в реальном времени.

Unhandled Rejection (TypeError): Cannot set property 'innerHTML' of undefined это ошибка, которую я получаю при выполнении функции handleVideoOnPlay

Я новичок в структуре react, было бы здорово, если бы кто-нибудь мне помог.

 import './App.css';
import * as faceapi from 'face-api.js'
import { useEffect, useRef, useState } from 'react';


function App() {
  const videoHeight = 480;
  const videoWidth = 640;
  const [initializing, setIntializing] = useState(false);
  const videoRef = useRef();
  const canvasRef = useRef();

  useEffect(()=>{
    const loadModels = async() => {
      const MODEL_URL = process.env.PUBLIC_URL   './models';
      setIntializing(true);
      Promise.all([
        faceapi.nets.tinyFaceDetector.loadFromUri(MODEL_URL),
        faceapi.nets.faceLandmark68Net.loadFromUri(MODEL_URL),
        faceapi.nets.faceRecognitionNet.loadFromUri(MODEL_URL),
        faceapi.nets.faceExpressionNet.loadFromUri(MODEL_URL),
        faceapi.nets.ageGenderNet.loadFromUri(MODEL_URL)
      ]).then(startVideo);
    }
    loadModels();
  },[])

  const startVideo =()=>{
    navigator.getUserMedia({
      video : {}
    }, stream => videoRef.current.srcObject = stream,  
     function(err) {
      console.log("The following error occurred: "   err.name);
   })
  }

  const handleVideoOnPlay =() =>{
    setInterval(async () =>{
      if(initializing){
        setIntializing(false);
      }
      canvasRef.current.innerHTML = faceapi.createCanvasFromMedia(videoRef.current);
      const displaySize ={
        width : videoWidth,
        height : videoHeight
      }
      faceapi.matchDimensions(canvasRef.current,displaySize);
      const detections = await faceapi.detectAllFaces(videoRef.current,new faceapi.TinyFaceDetectorOptions()).withFaceLandmarks().withFaceExpressions().withAgeAndGender();
      const resizedDetections = faceapi.resizeResults(detections,displaySize);
      canvasRef.current.getContext('2d').clearRect(0,0,videoWidth,videoHeight);
      faceapi.draw.drawDetections(canvasRef.current,resizedDetections);
      faceapi.draw.drawFaceLandmarks(canvasRef.current,resizedDetections);
      faceapi.draw.drawFaceExpressions(canvasRef.current,resizedDetections);
    //faceapi.draw.drawFaceExpressions(canvasRef.current,resizedDetections);

      
      console.log(detections)
    },1000)
  }
  return (
    <div className = "App">
      <span>{initializing ? 'initializing' : 'Ready'}</span>
      <div>
        <video ref ={videoRef} autoPlay muted height ={videoHeight} width={videoWidth} onPlay={handleVideoOnPlay}/>
        <canvas Ref={canvasRef} className="position-absolute"/>
        </div>
    </div>

  
  );
}

export default App;
 

У меня тоже есть еще один вопрос.
Прямо сейчас код использует веб-камеру, как изменить его на камеру телефона ?

Комментарии:

1. используйте ref вместо Ref для холста. Опечатка.

2. этот <canvas Ref

3. @Тушаршахи да работает

4. @somallg спасибо, что он работает, не могли бы вы рассказать мне, как изменить видеовход с веб-камеры на камеру телефона

Ответ №1:

Проблема: Cannot set property 'innerHTML' of undefined
Причина: canvasRef.current становится неопределенной

Прежде чем продолжить, я нашел одну вещь, в строке <canvas Ref={canvasRef} className="position-absolute"/> есть ссылка, она должна быть ref

Теперь, я думаю, вам следует использовать useEffect() следующее

 useEffect(()=>{
...
...
},[canvasRef])
 

ИЛИ
перезвоните в качестве справки

 <canvas ref={el => { console.log(el); canvasRef.current = el; }} // or setState(el)  
className="position-absolute"/>
 

Комментарии:

1. Спасибо, вы можете сказать мне, как изменить ввод веб-камеры на камеру телефона

2. @Doubtcoder Если этот ответ сработал, пожалуйста, сделайте его правильным ответом (отметьте галочкой). Пусть это будет полезно и для других. Вы тоже получите очки!

3. @Doubtcoder — Что касается вашего второго вопроса, я предлагаю задать его в новом посте. Шансы получить ваш вопрос высоки, если вы зададите каждый вопрос отдельно.