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

React.ts调用食谱API:嵌套对象数组类型定义及展示问题

解决React+TypeScript中嵌套API数据的类型定义问题

问题背景

使用React+TypeScript调用食谱API,能正常获取title、image、summary字段,但无法访问analyzedInstructions里的steps数据,核心问题是嵌套对象数组的TypeScript类型定义错误,同时存在拼写失误。

用户原组件代码

export function RecipeDetails() {
    const initialRecipeState = {
        title: '',
        analizedInstructions: [{
            steps: [{
                name: ''
            }]
        }],
        image: '',
        summary: ''
        
    }

    const { id } = useParams();
    const [data, setData] = useState<RecipeData>(initialRecipeState);

    useEffect( () => {
        const getData = async() => {
            const newData = await fetchData(`https://api.spoonacular.com/recipes/${id}/information?apiKey=key&includeNutrition=false`)
            setData(newData)
        }
        getData();
        console.log(data.analizedInstructions)
    },[])

用户原类型定义代码

export type RecipeData = {
    title: string,
    analizedInstructions: Steps,
    image: string,
    summary: string
}

export type Steps = {
    name: Name
}
export type Name = {
    name: string
}

解决方案

1. 修正TypeScript类型定义

根据API返回的结构(analyzedInstructions是数组,每个元素包含steps数组,steps对象包含number、step等字段),重新定义类型:

// 单个步骤的类型,按需添加字段
export type RecipeStep = {
  number: number;
  step: string;
};

// 单个烹饪说明的类型
export type RecipeInstruction = {
  name: string;
  steps: RecipeStep[];
};

// 顶级食谱数据类型
export type RecipeData = {
  title: string;
  analyzedInstructions: RecipeInstruction[]; // 明确为数组类型
  image: string;
  summary: string;
};

2. 修正组件代码

修正拼写错误,调整初始状态匹配类型,完善逻辑:

export function RecipeDetails() {
    // 初始状态匹配定义好的类型,修正拼写并设为空数组更合理
    const initialRecipeState: RecipeData = {
        title: '',
        analyzedInstructions: [],
        image: '',
        summary: ''
    }

    const { id } = useParams();
    const [data, setData] = useState<RecipeData>(initialRecipeState);

    useEffect(() => {
        const getData = async () => {
            if (!id) return; // 避免id为空时请求
            const newData = await fetchData(`https://api.spoonacular.com/recipes/${id}/information?apiKey=key&includeNutrition=false`)
            setData(newData)
        }
        getData();
    }, [id]) // 添加id作为依赖,id变化时重新请求

    // 示例:渲染步骤列表
    return (
        <div className="recipe-details">
            <h1>{data.title}</h1>
            <img src={data.image} alt={data.title} className="recipe-image" />
            {/* summary是HTML字符串,用dangerouslySetInnerHTML渲染 */}
            <div className="recipe-summary" dangerouslySetInnerHTML={{ __html: data.summary }} />
            
            <section className="recipe-steps">
                <h2>制作步骤</h2>
                {data.analyzedInstructions.map((instruction, idx) => (
                    <div key={idx} className="instruction-group">
                        {instruction.name && <h3>{instruction.name}</h3>}
                        <ol>
                            {instruction.steps.map((step) => (
                                <li key={step.number} className="step-item">
                                    <span className="step-number">{step.number}.</span> {step.step}
                                </li>
                            ))}
                        </ol>
                    </div>
                ))}
            </section>
        </div>
    )
}

关键修复点

  • 拼写修正:将代码中的analizedInstructions改为analyzedInstructions,与API返回字段名一致,否则无法读取数据。
  • 数组类型:analyzedInstructions是数组类型,类型定义中必须标注为RecipeInstruction[],而非单个对象。
  • 依赖优化:给useEffect添加id依赖项,确保id变化时重新请求数据,同时增加id非空判断避免无效请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 05:48:24