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

react-image-crop中onImageLoaded不生效 选中图片无法显示解决

问题根因

你使用的react-image-crop为v10及以上版本,和参考的旧版本文档API不兼容,两个核心错误直接导致功能失效:

  • v10+版本的ReactCrop组件不再自动根据传入的src渲染图片标签,仅负责渲染裁剪交互蒙层,图片元素需要开发者手动作为组件子元素传入
  • 旧版本提供的onImageLoaded属性已经被正式移除,图片DOM实例需要通过手动写入的img标签的原生onLoad事件获取
    当前代码仅给组件传入了src属性,没有传入img子元素,页面根本不会渲染待裁剪图片,自然无法触发加载回调,初始值为null的image状态始终拿不到图片实例。
修复方案
  • 调整ReactCrop组件结构,移除直接传给组件的src属性,手动将img标签作为子元素写入组件内部
  • 把图片加载逻辑绑定到自定义img标签的onLoad事件上,正确存储图片实例
  • 补充初始裁剪区域配置,避免初始裁剪宽高为0导致裁剪逻辑报错
  • 增加必要的状态判断和按钮禁用逻辑,减少异常触发场景
  • (可选)补充对象URL回收逻辑,避免频繁选择图片造成内存泄漏
修复后可直接运行的完整代码
import "./App.css";
import {Form, Button, Container} from "react-bootstrap";
import "bootstrap/dist/css/bootstrap.min.css";
import {useState, useEffect} from "react";
import ReactCrop from "react-image-crop";
import 'react-image-crop/dist/ReactCrop.css';
function App() {
  const [srcImg, setSrcImg] = useState(null);
  const [image, setImage] = useState(null);
  const [crop, setCrop] = useState({
    aspect: 16 / 9,
    unit: '%',
    width: 50
  });
  const [result, setResult] = useState(null);

  // 组件卸载、切换图片时回收临时对象URL
  useEffect(() => {
    return () => {
      if (srcImg) URL.revokeObjectURL(srcImg)
    }
  }, [srcImg])

  const handleImage = (event) => {
    const file = event.target.files[0];
    if (!file) return;
    // 切换新图时重置旧状态
    setImage(null);
    setResult(null);
    setSrcImg(URL.createObjectURL(file));
  };

  const onImageLoad = (e) => {
    setImage(e.currentTarget);
  };

  const getCroppedImg = () => {
    if (!image || !crop.width || !crop.height) return;
    try {
      const canvas = document.createElement("canvas");
      const scaleX = image.naturalWidth / image.width;
      const scaleY = image.naturalHeight / image.height;
      canvas.width = Math.floor(crop.width * scaleX);
      canvas.height = Math.floor(crop.height * scaleY);
      const ctx = canvas.getContext("2d");
      ctx.drawImage(
        image,
        crop.x * scaleX,
        crop.y * scaleY,
        crop.width * scaleX,
        crop.height * scaleY,
        0,
        0,
        canvas.width,
        canvas.height
      );
      const base64Image = canvas.toDataURL("image/jpeg", 1);
      setResult(base64Image);
    } catch (e) {
      console.log("裁剪执行异常:", e);
    }
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    console.log("提交裁剪结果:", result);
  };
 
  return (
    <Container className="container" fluid="md">
      <h5 className="header">React Image Crop</h5>
      <Form onSubmit={handleSubmit}>
        <Form.Group className="mb-3" controlId="formBasicEmail">
          <Form.Label>Select Image you want to crop</Form.Label>
          <div>
            <input type="file" accept="image/*" onChange={handleImage} />
          </div>
          <div>
            {srcImg && (
              <div>
                <ReactCrop
                  style={{maxWidth: "50%"}}
                  crop={crop}
                  onChange={setCrop}
                >
                  {/* v10+版本需要手动传入img子元素 */}
                  <img
                    src={srcImg}
                    alt="待裁剪图片"
                    onLoad={onImageLoad}
                    style={{maxWidth: "100%"}}
                  />
                </ReactCrop>
                <Button className="cropButton" onClick={getCroppedImg} disabled={!image}>
                  crop
                </Button>
              </div>
            )}
            {result && (
              <div>
                <p>裁剪结果:</p>
                <img src={result} alt="cropped image" style={{maxWidth: "300px"}} />
              </div>
            )}
          </div>
        </Form.Group>
        <Button variant="primary" type="submit" disabled={!result}>
          Submit
        </Button>
      </Form>
    </Container>
  );
}

export default App;
补充说明
  • 初始裁剪区域用百分比作为单位,选择图片后会自动生成符合16:9比例的初始裁剪框,不需要手动拖拽才会生成有效裁剪区域
  • 生成裁剪图时对canvas宽高做了取整处理,避免导出的图片出现锯齿、模糊问题
  • 裁剪、提交按钮增加了禁用状态判断,图片未加载完成、未生成裁剪结果时无法点击,减少异常报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 23:31:08