You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中react-cropper调用getCroppedCanvas报TypeError求助

问题分析与修复方案

错误原因

出现TypeError: Cannot read properties of null (reading 'getCroppedCanvas')的核心原因有三点:

  • React-Cropper的ref使用错误:你直接调用cropperRef.current.getCroppedCanvas(),但react-cropper的ref指向的是组件实例,底层的cropperjs实例需要通过cropperRef.current.cropper访问,getCroppedCanvas是cropperjs实例的方法,不是组件实例的方法。
  • 无效的图片源类型:uploadedImage的prop类型定义为PropTypes.node,但react-cropper的src属性需要的是图片URL字符串(或base64),如果传入的是React节点(比如<img>元素),会导致cropper无法正确初始化实例。
  • 初始渲染时的非法访问:组件顶层的console.log(cropperRef.current.getCroppedCanvas)会在组件首次渲染时执行,此时cropperRef.current还未被赋值,直接访问会触发null错误。

修复后的代码

import { useState, useRef, useEffect } from 'react';
import Cropper from 'react-cropper';
import 'cropperjs/dist/cropper.css';
import PropTypes from 'prop-types';

const ImageEditor = ({ uploadedImage }) => {
  const [cropData, setCropData] = useState("#");
  const cropperRef = useRef(null);
  
  const getCropData = () => {
    // 先检查cropper实例是否存在
    if (cropperRef.current?.cropper) {
      console.log('click');
      const croppedCanvas = cropperRef.current.cropper.getCroppedCanvas({
        // 明确指定1:1的裁剪尺寸,可选
        width: 300,
        height: 300
      });
      if (croppedCanvas) {
        const dataUrl = croppedCanvas.toDataURL();
        setCropData(dataUrl);
      }
    }
  };

  // 可选:在cropper初始化后打印实例,避免初始渲染报错
  useEffect(() => {
    if (cropperRef.current?.cropper) {
      console.log('Cropper initialized:', cropperRef.current.cropper);
    }
  }, [uploadedImage]); // 依赖uploadedImage,确保图片更新后重新检查

  return (
    <div>
      <div style={{ width: "100%" }}>
        <Cropper
          ref={cropperRef}
          style={{ width: "100%" }}
          zoomTo={1}
          aspectRatio={1}
          src={uploadedImage}
          viewMode={1}
          background={false}
          responsive={true}
          autoCropArea={1}
          checkOrientation={false}
          guides={false}
        />
      </div>
      <div>
        <div
          className="box"
          style={{ width: "50%", float: "right", height: "300px" }}
        >
          <h1>
            <span>Crop</span>
            <button style={{ float: "right" }} onClick={getCropData}>
              Crop Image
            </button>
          </h1>
          <img style={{ width: "100%" }} src={cropData} alt="cropped" />
        </div>
      </div>
      <br style={{ clear: "both" }} />
    </div>
  );
};

// 修正prop类型为字符串(图片URL/base64)
ImageEditor.propTypes = {
  uploadedImage: PropTypes.string.isRequired
};

export default ImageEditor;

额外说明

  • 确保传入uploadedImage的是有效的图片URL(本地路径、远程地址或base64字符串),而非React节点。
  • 使用可选链操作符?.可以更安全地访问嵌套属性,避免null/undefined报错。
  • 若需要精确控制裁剪后的尺寸,可以在getCroppedCanvas中传入width和height参数,确保输出1:1比例的画布。

内容的提问来源于stack exchange,提问作者HyeJi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 10:12:27