Как избежать повторного рендеринга при использовании useRef? - PullRequest
1 голос
/ 17 января 2020

Я создаю компонент для фотографирования и загрузки на сервер. Когда я что-то печатаю в поле ввода, setTitle запускается, и компонент перерисовывается. Когда это происходит, видео становится черным. Как я могу избежать рендеринга видео?

function Camera() {
  console.log("Render camera");
  const [title, setTitle] = useState("");
  let videoRef = useRef(null);
  let canvasRef = useRef();

// This is a custom hook for get the camera input
  const mediaStream = useUserMedia({
    audio: false,
    video: { width: 300, height: 300 }
  });

  if (mediaStream && videoRef.current && !videoRef.current.srcObject) {
    videoRef.current.srcObject = mediaStream;
  }

  // Stop the video stream when component is unmount
  useEffect(() => {
    return () => {
      if (mediaStream) {
        mediaStream.getTracks()[0].stop();
      }
    };
  }, [mediaStream]);

  const handlePostTitle = e => {
    e.preventDefault();
    setTitle(e.target.value);
  };

  const onCapture = async blob => {
    console.log("Upload to server");
  };

  return (
    <form>
      <div>
        <video ref={videoRef} autoPlay muted />
        <canvas ref={canvasRef} width={300} height={300} />
      </div>
      <div>
        <input
          type="text"
          name="title"
          value={title}
          onChange={handlePostTitle}
          placeholder="Title"
        />
      </div>
      <button
        type="submit"
        onClick={() => {
          if (canvasRef) {
            const context = canvasRef.current.getContext("2d");
            // This is for rotate the photo
            context.translate(300, 0);
            context.scale(-1, 1);

            context.drawImage(videoRef.current, 0, 0, 300, 300);
            canvasRef.current.toBlob(blob => onCapture(blob), "image/jpeg", 1);
            context.clearRect(0, 0, 300, 300);
          }
        }}
      >
        Take photo
      </button>
    </form>
  );
}

Полный код доступен по адресу https://codesandbox.io/s/react-camera-component-with-hooks-s6pmb

1 Ответ

1 голос
/ 17 января 2020

Попробуйте этот код, ссылка Codesandbox - https://codesandbox.io/s/react-camera-component-with-hooks-n9ey9

import React, { useState, useRef, useEffect } from "react";
import ReactDOM from "react-dom";
import { useUserMedia } from "./hooks/use-user-media";

function Camera() {
  console.log("Render camera");
  let videoRef = useRef(null);
  let canvasRef = useRef();

  const mediaStream = useUserMedia({
    audio: false,
    video: { width: 300, height: 300 }
  });

  if (mediaStream && videoRef.current && !videoRef.current.srcObject) {
    videoRef.current.srcObject = mediaStream;
  }

  // Stop the video stream when component is unmount
  useEffect(() => {
    return () => {
      if (mediaStream) {
        mediaStream.getTracks()[0].stop();
      }
    };
  }, [mediaStream]);

  const onCapture = async blob => {
    console.log("Upload to server");
  };

  let titleRef = useRef();

  const OnSubmit = () => {
    console.log("title", titleRef.current.value);
  };

  return (
    <form>
      <div>
        <video ref={videoRef} autoPlay muted />
        <canvas ref={canvasRef} width={300} height={300} />
      </div>
      <div>
        <input type="text" name="title" placeholder="Title" ref={titleRef} />
      </div>
      <button
        type="submit"
        onClick={() => {
          OnSubmit();
          if (canvasRef) {
            const context = canvasRef.current.getContext("2d");
            // This is for rotate the photo
            context.translate(300, 0);
            context.scale(-1, 1);

            context.drawImage(videoRef.current, 0, 0, 300, 300);
            canvasRef.current.toBlob(blob => onCapture(blob), "image/jpeg", 1);
            context.clearRect(0, 0, 300, 300);
          }
        }}
      >
        Take photo
      </button>
    </form>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<Camera />, rootElement);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...