简体   繁体   中英

Convert Class Component to Functional Component

I will try to explain the task and then tell you my problem. My task is to add a webcam component which can take a picture and then upload the picture on click of button.

I am using react-webcam library, this one: https://www.npmjs.com/package/react-webcam And have a created a class component “ class UploadPhoto extends Component ” in which I am rendering the react-webcam (Webcam tag ) and able to display the webcam successfully.

However, when I add the following attribute ( ref={webcamRef} ) to tag, I receive an error that I am making an invalid hookcall, because webcamRef is initalized to a hook useRef(null). As below:

const webcamRef = React.useRef(null);

Error:

Uncaught Invariant Violation: Invalid hook call. Hooks can only be called inside of the body of a function component.

I am aware that we cannot call hooks in the class component, so my question is how do I convert my class component into a functional component, so that I can use this hook, which will help me to capture a photo.

Please let me know if you need any more information from me.

Thank you. PS - I am fairly new to ReactJS and trying my way in to learn it.

Following is my class component for UploadPhoto:

import React, { Fragment, useRef, Component } from 'react';
import ReactDOM from 'react-dom';
import { Camera } from '../../lib';
import Header from '../header';
import Webcam from "react-webcam";

import {
    Button,
} from 'reactstrap';
import axios from "axios/index";

class UploadPhoto extends Component {

constructor(props) {
    super(props);
    this.capture = this.capture.bind(this)
    this.next = this.next.bind(this)
}

capture(imgSrc) {
    console.log("image captured : " + imgSrc);
}

next() {
    console.log("next button clicked")
    //go to review details component
   // this.props.history.push("/review-details");
}

render() {
    const webcamRef = React.useRef(null);
    return (
        <div className="text-center">
            <div>
                Take a Picture
            </div>
            <Webcam
                audio={false}
                height={500}
                ref={webcamRef}
                screenshotFormat="image/jpeg"
                width={600} >
            <Button className="position-relative text-center" onClick={this.capture}>Capture photo</Button>
                </Webcam>
            <div>
            <Button className="position-relative text-center btn-start" onClick={this.next}>NEXT</Button>
            </div>
        </div>
    );
}
}
export default UploadPhoto;

While you could convert your component to a functional component, that's not necessary to solve this issue. Refs can be used in class components too, you just can't do so with useRef . Instead, use createRef :

constructor(props) {
    super(props);
    this.capture = this.capture.bind(this)
    this.next = this.next.bind(this)
    this.webcamRef = React.createRef();
}

componentDidMount() {
    const imageSrc = this.webcamRef.current.getScreenshot();
    this.capture(imagesrc);
}

render() {
    return (
        <div className="text-center">
            <div>
                Take a Picture
            </div>
            <Webcam
                audio={false}
                height={500}
                ref={this.webcamRef}
                screenshotFormat="image/jpeg"
                width={600} >
            <Button className="position-relative text-center" onClick={this.capture}>Capture photo</Button>
                </Webcam>
            <div>
            <Button className="position-relative text-center btn-start" onClick={this.next}>NEXT</Button>
            </div>
        </div>
    );
}

Since the question was how to convert class to functional component, here's the same component as a function:

import React, { Fragment, useRef, Component } from 'react';
import ReactDOM from 'react-dom';
import { Camera } from '../../lib';
import Header from '../header';
import Webcam from "react-webcam";

import {
    Button,
} from 'reactstrap';
import axios from "axios/index";

const UploadPhoto = props => {
    const webcamRef = useRef(null);
    const capture = () => {
        const imgSrc = webcamRef.current.getScreenshot();
        console.log("image captured : " + imgSrc);
    }
    const next = () => {
        console.log("next button clicked");
        //go to review details component
       // props.history.push("/review-details");
    }
    return (
        <div className="text-center">
            <div>
                Take a Picture
            </div>
            <Webcam
                audio={false}
                height={500}
                ref={webcamRef}
                screenshotFormat="image/jpeg"
                width={600} >
            <Button className="position-relative text-center" onClick={capture}>Capture photo</Button>
                </Webcam>
            <div>
            <Button className="position-relative text-center btn-start" onClick={next}>NEXT</Button>
            </div>
        </div>
    )
}

export default UploadPhoto;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM