如何将React Hooks版摄像头录制代码改写为可复用类组件
改写完成的可复用摄像头录制类组件
核心映射规则
从函数组件 Hooks 逻辑迁移到类组件的对应关系:
- 原
useRef(null)创建的持久化引用,替换为构造函数内用React.createRef()初始化的实例属性 - 原
useState维护的响应式状态,迁移到类的this.state中,所有状态更新统一使用this.setState()触发重渲染 - 原
useCallback包裹的事件处理函数,替换为类的实例方法,在构造函数中显式绑定this指向,避免执行时上下文丢失
注意:类组件中禁止直接修改
this.state的属性值,这类操作不会触发组件重渲染。
完整组件代码
import React from "react"; import Webcam from "react-webcam"; export default class WebcamStreamCapture extends React.Component { constructor(props) { super(props); // 初始化DOM引用,等价于原函数组件的两个useRef this.webcamRef = React.createRef(); this.mediaRecorderRef = React.createRef(); // 初始化状态,等价于原函数组件的两个useState this.state = { capturing: false, recordedChunks: [] }; // 绑定实例方法的this指向 this.handleStartCaptureClick = this.handleStartCaptureClick.bind(this); this.handleDataAvailable = this.handleDataAvailable.bind(this); this.handleStopCaptureClick = this.handleStopCaptureClick.bind(this); this.handleDownload = this.handleDownload.bind(this); } handleStartCaptureClick() { this.setState({ capturing: true }); // 初始化媒体录制器 this.mediaRecorderRef.current = new MediaRecorder(this.webcamRef.current.stream, { mimeType: "video/webm" }); // 绑定录制数据回调 this.mediaRecorderRef.current.addEventListener( "dataavailable", this.handleDataAvailable ); this.mediaRecorderRef.current.start(); // 触发父组件录制开始回调 if (typeof this.props.onRecordingStart === "function") { this.props.onRecordingStart(); } } handleDataAvailable({ data }) { // 收集录制分片 if (data.size > 0) { this.setState((prevState) => ({ recordedChunks: [...prevState.recordedChunks, data] })); } } handleStopCaptureClick() { this.mediaRecorderRef.current.stop(); this.setState({ capturing: false }); } handleDownload() { const { recordedChunks } = this.state; if (!recordedChunks.length) return; // 生成录制视频Blob const videoBlob = new Blob(recordedChunks, { type: "video/webm" }); // 将生成的Blob透传给父组件做自定义处理 if (typeof this.props.onDataReady === "function") { this.props.onDataReady(videoBlob); } // 内置下载逻辑,可根据业务需要移除 const url = URL.createObjectURL(videoBlob); const downloadLink = document.createElement("a"); document.body.appendChild(downloadLink); downloadLink.style = "display: none"; downloadLink.href = url; downloadLink.download = "react-webcam-stream-capture.webm"; downloadLink.click(); window.URL.revokeObjectURL(url); this.setState({ recordedChunks: [] }); } render() { const { capturing, recordedChunks } = this.state; return ( <> <Webcam audio={false} ref={this.webcamRef} /> {capturing ? ( <button onClick={this.handleStopCaptureClick}>Stop Capture</button> ) : ( <button onClick={this.handleStartCaptureClick}>Start Capture</button> )} {recordedChunks.length > 0 && ( <button onClick={this.handleDownload}>Download</button> )} </> ); } }
组件扩展说明
为了适配独立组件的复用需求,组件预留了两个对外回调接口:
onRecordingStart:录制流程正式启动时触发,可用于通知父组件切换按钮状态、展示录制提示onDataReady:录制完成、生成可处理的视频Blob对象时触发,将Blob作为参数传入,父组件可直接用于上传、本地存储、二次编辑等自定义逻辑- 组件内置的下载按钮和对应逻辑不影响核心录制功能,可根据使用场景完全移除
内容的提问来源于stack exchange,提问作者galgo
相关产品推荐
相关产品推荐

