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

Next.js中如何将<img>标签替换为新版Image组件

解决Next.js Image组件替换img后的构造错误

问题场景

将图片上传预览组件中的原生<img>替换为Next.js最新版Image组件后,出现错误:

TypeError: Failed to construct 'Image': Please use the 'new' operator, this DOM object constructor cannot be called as a function

错误原因

  1. 未导入Next.js Image组件:代码中使用<Image>标签但未从next/image导入,浏览器将其识别为原生DOM的Image构造函数,触发调用方式错误。
  2. Next.js Image属性要求:最新版Image组件对本地/Base64格式图片需额外配置,且默认需要width/height属性,或使用fill模式适配父容器布局。

修复步骤

  1. 导入Next.js官方Image组件
  2. 针对Base64预览图设置unoptimized={true},禁用不必要的远程图片优化
  3. 使用fill模式配合父容器的相对定位,保持原有的自适应尺寸和图片适配效果

完整修复代码

import React, { useState, useRef, useEffect } from "react";
// 导入Next.js Image组件
import Image from "next/image";

const ImageUploadCard = () => {
  const componentRef = useRef(null);
  const [componentWidth, setComponentWidth] = useState(0);
  const [componentHeight, setComponentHeight] = useState(0);

  useEffect(() => {
    function updateComponentWidth() {
      if (componentRef.current) {
        const width = componentRef.current.getBoundingClientRect().width;
        const height = componentRef.current.getBoundingClientRect().height;
        setComponentWidth(width);
        setComponentHeight(height);
      }
    }

    updateComponentWidth();
    window.addEventListener("resize", updateComponentWidth);
    return () => window.removeEventListener("resize", updateComponentWidth);
  }, []);

  const inputRef = useRef(null);
  const [previewImage, setPreviewImage] = useState(null);

  const handleImageChange = (event) => {
    const file = event.target.files[0];
    if (file && file.size > 5242880) {
      console.log("File size exceeds the maximum limit (5MB)");
      return;
    }
    if (file) {
      const reader = new FileReader();
      reader.onloadend = () => setPreviewImage(reader.result);
      reader.readAsDataURL(file);
    } else {
      setPreviewImage(null);
    }
  };

  return (
    <div ref={componentRef} className="mb-6 md:pr-2">
      <div
        style={{ width: componentWidth }}
        className="dark:bg-jacarta-700 dark:border-jacarta-600 border-jacarta-100 group relative flex flex-col items-center justify-center rounded-lg border-2 border-dashed bg-white py-20 px-5 text-center"
        onClick={() => inputRef.current.click()}
      >
        <div className="relative z-10 cursor-pointer">
          <svg
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 24 24"
            width="24"
            height="24"
            className="fill-jacarta-500 mb-4 inline-block dark:fill-white"
          >
            <path fill="none" d="M0 0h24v24H0z" />
            <path d="M16 13l6.964 4.062-2.973.85 2.125 3.681-1.732 1-2.125-3.68-2.223 2.15L16 13zm-2-7h2v2h5a1 1 0 0 1 1 1v4h-2v-3H10v10h4v2H9a1 1 0 0 1-1-1v-5H6v-2h2V9a1 1 0 0 1 1-1h5V6zM4 14v2H2v-2h2zm0-4v2H2v-2h2zm0-4v2H2V6h2zm0-4v2H2V2h2zm4 0v2H6V2h2zm4 0v2h-2V2h2zm4 0v2h-2V2h2z" />
          </svg>
          <p className="dark:text-jacarta-300 mx-auto max-w-xs text-xs">
            Image formats: JPEG, PNG, JPG . Max size: 5 MB
          </p>
          <label>
            <input
              type="file"
              accept=".jpg, .jpeg, .png"
              onChange={handleImageChange}
              style={{ display: "none" }}
              ref={inputRef}
              max="5242880"
            />
          </label>
        </div>
      </div>

      {previewImage && (
        <div
          className="dark:bg-jacarta-700 dark:border-jacarta-600 border-jacarta-100 group relative flex items-center justify-center rounded-lg border-2 border-dashed bg-white py-20 px-5 text-center"
          style={{ width: componentWidth, height: 400 }}
        >
          <Image
            src={previewImage}
            alt="Preview"
            fill
            unoptimized={true}
            style={{ objectFit: "cover" }}
          />
        </div>
      )}
    </div>
  );
};

export default ImageUploadCard;

关键说明

  • fill属性让Image组件填充整个父容器,依赖父容器的relative定位(已通过className实现)
  • unoptimized={true}针对Base64图片禁用Next.js的远程优化逻辑,避免无效处理
  • 完整保留了原有的文件大小校验、动态宽度计算等所有业务逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 20:43:09