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

React组件中require加载图片路径失败问题求助

问题描述

在React组件RecipeComp中,通过接口获取的data.type和data.url能在第2、3行的<p>标签正常渲染,但在第1行通过require拼接路径传入RecipeProfileImg组件时失败,控制台报错Cannot find module './undefined/undefined'。尝试用模板字符串../../Assets/Images/${data.type}/${data.url}写法后问题依旧,已确认路径本身正确,请问问题原因是什么?

组件代码

import { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
import RecipeService from "./RecipeService";
import RecipeProfileImg from "./RecipeProfileImg";
import "../../Assets/css/recipePage.css";

const RecipeComp = () => {

    const {id} = useParams();

    const [data, setData] = useState({});

    /*const [data, setData] = useState({
        name: 'name1',
        type: 'tipo1',
        url: 'path1',
        ingredients: 'ingr1',
        method: 'meth1',
        preparationTime: 10,
        cookingTime: 10
    });*/

    useEffect(() => {
        RecipeService.readRecipeById(id).then((res) => {
            console.log(res.data.type);
            setData(res.data);
        });
    }, [id]);

    function splitIngredients(ingrs){
        const pieces = ingrs.split(", ");
        const listItems = [];
        for(let i = 0; i < pieces.length; i++){
            const elem = <li>{pieces[i]}</li>;
            listItems.push(elem);
        }
        return listItems;
    }

    return(
        <div>
            <h1>{data.name}</h1>
            <RecipeProfileImg imgSrc={require("../../Assets/Images/" + data.type + "/" + data.url)} />
            <p id={data.url}>{data.type}</p>
            <p id={data.type}>{data.url}</p>
            <div className="listsBox">
                <label className="listLab">Ingredienti:
                    <ul className="listx">
                        {
                            splitIngredients(data.ingredients)
                        }
                    </ul>
                </label>
                <label className="listLab">Tempi:
                    <ul className="listx">
                        <li>Tempo di Preparazione: {data.preparationTime} min</li>
                        <li>Tempo di Cottura: {data.cookingTime} min</li>
                    </ul>
                </label>
            </div>
            <h3 className="prepTitle">Preparazione</h3>
            <p className="methodPar">{data.method}</p>
            <a href={'/recipes/delete/' + id}>delete me</a>
            <br />
            <a href={'/recipes/update/' + id}>update me</a>
        </div>
    );
}

export default RecipeComp;

问题代码行

1) <RecipeProfileImg imgSrc={require("../../Assets/Images/" + data.type + "/" + data.url)} />
2) <p id={data.url}>{data.type}</p>
3) <p id={data.type}>{data.url}</p>

原因分析及解决方案

核心原因

require是Webpack等打包工具在编译阶段执行的静态资源加载方法,它无法识别运行时动态生成的路径。

组件初始化时,data的初始值是空对象{},此时data.type和data.url都是undefined,第一次渲染时会执行require("../../Assets/Images/undefined/undefined"),直接触发找不到模块的错误——即便后续接口返回数据更新了data,也无法修复这次编译阶段的错误。

而<p>标签里的{data.type}和{data.url}是运行时的插值渲染,初始时显示空或undefined,等接口数据返回后会自动更新,所以不会报错。

解决方案

方案1:条件渲染,确保数据存在后再加载图片

在require外层加判断,只有当data.type和data.url都存在时才执行加载:

<RecipeProfileImg 
  imgSrc={data.type && data.url ? require(`../../Assets/Images/${data.type}/${data.url}`) : null} 
/>

同时在RecipeProfileImg组件里处理imgSrc为null的情况(比如显示占位图)。

方案2:改用ES模块动态导入(推荐)

使用import()动态导入图片,这是运行时加载方式,适配动态路径场景:

// 新增状态存储图片地址
const [imgSrc, setImgSrc] = useState(null);

useEffect(() => {
  if (data.type && data.url) {
    import(`../../Assets/Images/${data.type}/${data.url}`)
      .then(imgModule => setImgSrc(imgModule.default))
      .catch(err => console.error("图片加载失败", err));
  }
}, [data.type, data.url]);

渲染时直接使用状态里的图片地址:

<RecipeProfileImg imgSrc={imgSrc} />

方案3:将图片放在public目录,使用绝对路径

如果把图片放在项目的public文件夹下,可直接用字符串拼接路径,无需require:

<RecipeProfileImg 
  imgSrc={data.type && data.url ? `/Assets/Images/${data.type}/${data.url}` : null} 
/>

注意:这种方式下Webpack不会对图片进行打包优化,需根据项目需求选择。


内容的提问来源于Stack Exchange,提问作者Andrea Zak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 11:01:25