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

React图片裁剪器报错Cannot read properties of null 问题求助

问题分析与解决方案

报错原因

  1. 状态未初始化或未加载完成:点击裁剪按钮时,若图片还未完成加载(image仍为null),或用户未拖动裁剪框生成有效区域(crop的width/height为null),访问image.naturalWidth或crop.width会触发Cannot read properties of null错误。
  2. ReactCrop API使用错误:新版react-image-crop(v10+)的裁剪区域变更回调应为onCropChange,而非旧版的onChange,导致裁剪状态无法正确更新。
  3. 额外img标签干扰:手动添加的<img>与ReactCrop内部的图片元素分离,导致裁剪逻辑绑定的image并非显示的图片,进而裁剪功能失效。

修复后的完整代码

import "./styles.css";
import React, { useState } from "react";
import ReactCrop from 'react-image-crop';
import 'react-image-crop/dist/ReactCrop.css'

export default function App() {
  const [src, setSrc] = useState(null);
  const [image, setImage] = useState(null);
  const [crop, setCrop] = useState({ aspect: 16 / 9 });
  const [result, setResult] = useState(null);

  const onImageChange = (event) => {
    if (event.target.files && event.target.files[0]) {
      setSrc(URL.createObjectURL(event.target.files[0]));
      // 选择新图时重置裁剪状态
      setResult(null);
      setCrop({ aspect: 16 / 9 });
    }
  };

  function getCroppedImg() {
    // 校验裁剪前置条件
    if (!image || !crop.width || !crop.height) {
      alert("请先拖动裁剪框选择有效区域");
      return;
    }

    const canvas = document.createElement('canvas');
    const scaleX = image.naturalWidth / image.width;
    const scaleY = image.naturalHeight / image.height;
    canvas.width = crop.width;
    canvas.height = crop.height;
    const ctx = canvas.getContext('2d');
    
    ctx.drawImage(
      image,
      crop.x * scaleX,
      crop.y * scaleY,
      crop.width * scaleX,
      crop.height * scaleY,
      0,
      0,
      crop.width,
      crop.height
    );
    
    const base64Image = canvas.toDataURL('image/jpeg');
    setResult(base64Image);
  }

  return (
    <div className="container">
      <div className='row'>
        <div className='col-6'>
          <input type="file" accept='image/*' onChange={onImageChange}/>
        </div>
        {src && (
          <div className='col-6'>
            <ReactCrop 
              src={src} 
              onImageLoaded={setImage} 
              crop={crop} 
              onCropChange={setCrop} 
              ruleOfThirds 
            />
            <button className='btn btn-danger' onClick={getCroppedImg}> 
              Crop Image 
            </button>
          </div>
        )}
        {result && (
          <div className='col-6'> 
            <img src={result} alt='Cropped Image' className='img-fluid' /> 
          </div>
        )}
      </div>
    </div>
  );
}

关键修复点

  • 空值校验:在裁剪函数开头添加对image和crop的有效性检查,避免访问null属性报错。
  • API适配:将onChange替换为新版react-image-crop的onCropChange,确保裁剪状态同步正确。
  • 移除冗余元素:删除手动添加的<img>标签,依赖ReactCrop内部渲染的图片,保证裁剪逻辑绑定正确的图片元素。
  • 状态重置:选择新图片时重置裁剪结果和状态,避免旧状态干扰新图裁剪。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 18:00:53