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

NextJS 13中如何从JSON获取图片路径并引用public目录图片?

问题与解决方案

现有代码

1. getData.ts

export async function getData(){
    const res = await fetch("http://localhost:3001/projects")
    return res.json()
}

2. 接口返回的JSON格式

{
    "projects": [{ 
        "title": "Project 1",
        "description": "Description 1",
        "tags": ["example", "notReal", "placeholder", "lol", "rofl"],
        "imageURL": "project1IMG"
    },{
        "title": "Project 2",
        "description": "Description 2",
        "tags": ["you", "get", "the", "idea"],
        "imageURL": "project2IMG"
    }]
}

3. Projects组件(Test.tsx)

import React from "react"
import { getData } from "@/lib/getdata"
import Project from "./project"

export default async function Test() {
    interface projectType{
        title: string,
        description: string,
        tags: [],
        imageURL: string
    }

    const projects: projectType[] = await getData()
    return (
        <section className="group">
        <div>
            {
                projects.map((project, index) => (
                    <React.Fragment key={index}>
                    <Project {...project} />
                    </React.Fragment>
                ))
            }
        </div>
    </section>
      )
}

4. Project组件

import Image from "next/image"

type ProjectProps = typeof projectsData[0]

export default function Project({ 
    title, 
    description, 
    tags, 
    imageURL,
}: ProjectProps){
    return (
       <div>
        <h1>{title}</h1>
        <p>{description}</p>
        <ul>
            {tags.map((tag: string, index: number) => (
                <li
                key={index}>{tag}</li>
            ))}
        </ul>
      <Image 
        src={imageURL}
        alt="placeholder"
        width="100"
        height="100"  
        /> 
        </div>
    )
}

核心问题解决

一、引用@/public目录下的图片

Next.js中public目录下的资源可通过根相对路径直接访问,比如public/projects/project1IMG.jpg对应访问路径为/projects/project1IMG.jpg。按以下步骤调整:

  1. 统一图片存储路径:把所有项目图片放在public的子目录中,比如public/projects/。
  2. 调整组件中Image的src属性:拼接基础路径与JSON返回的imageURL:
    <Image 
      src={`/projects/${imageURL}`} // 若JSON中imageURL不带后缀,可拼接为`/projects/${imageURL}.jpg`
      alt={title} // 替换占位符为项目标题,提升可访问性
      width={100}
      height={100}  
    />
    
    若图片直接放在public根目录,路径简化为/${imageURL}即可。

二、修正TypeScript类型声明

  1. 规范Projects组件中的类型定义:
    明确tags为字符串数组,同时修正getData返回值的类型断言:

    // 改用大驼峰命名符合TS规范
    interface ProjectType {
        title: string;
        description: string;
        tags: string[]; // 替换原空数组类型
        imageURL: string;
    }
    
    // getData返回的是包含projects数组的对象,需调整类型匹配
    const { projects }: { projects: ProjectType[] } = await getData();
    
  2. 修正Project组件的Props类型:
    复用定义好的ProjectType接口,避免依赖不存在的变量:

    import Image from "next/image";
    // 可将类型单独抽离到@/types/project.ts中,方便多处引用
    import type { ProjectType } from "./Test";
    
    export default function Project({ 
        title, 
        description, 
        tags, 
        imageURL,
    }: ProjectType){
        return (
           <div>
            <h1>{title}</h1>
            <p>{description}</p>
            <ul>
                {tags.map((tag, index) => ( // TS会自动推导tag类型,无需额外声明
                    <li key={index}>{tag}</li>
                ))}
            </ul>
          <Image 
            src={`/projects/${imageURL}`}
            alt={title}
            width={100}
            height={100}  
          /> 
            </div>
        )
    }
    

额外优化建议

  • 避免用index作为map的key,优先使用项目的唯一标识(若JSON中存在id字段)。
  • 在getData中添加错误处理,防止请求失败导致页面崩溃:
    export async function getData(){
        const res = await fetch("http://localhost:3001/projects")
        if (!res.ok) {
            throw new Error('获取项目数据失败');
        }
        return res.json()
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 22:10:03