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

如何访问API并映射数据?API调用与数据渲染问题求助

问题分析与解决方案

核心问题拆解

  • 状态处理错误:将API返回的数组转为字符串,导致无法使用map遍历
  • 初始状态缺失:未给newsList设置初始空数组,首次渲染时undefined.map会报错
  • 异步代码冗余:async函数混用.then,写法不够简洁
  • 错误边界缺失:未处理newsList加载前的状态,可能引发渲染错误

修正后的代码

NewsList组件修正

import React from 'react';
import { useState, useEffect } from 'react'
import { getNews } from '../../api/drupalAPI'

export const NewsList = () => {
    // 初始状态设为空数组,避免首次渲染map报错
    const [newsList, setNewsList] = useState([]);
    // 添加加载状态,优化用户体验
    const [isLoading, setIsLoading] = useState(true);
    const [error, setError] = useState<string | null>(null);

    const fetchNewsList = async () => {
        try {
            // 用await替代.then,让异步逻辑更清晰
            const response = await getNews();
            // 直接存入数组,不要转成字符串
            setNewsList(response);
            setError(null);
        } catch (err) {
            console.error('获取新闻列表失败:', err);
            setError('加载新闻失败,请稍后重试');
            // 出错时重置列表为空数组
            setNewsList([]);
        } finally {
            setIsLoading(false);
        }
    }

    useEffect(() => {
        fetchNewsList();  
    }, []);

    // 加载状态提示
    if (isLoading) {
        return <div>加载中...</div>;
    }

    // 错误状态提示
    if (error) {
        return <div>{error}</div>;
    }

    return (
        <div>
            {newsList.length === 0 ? (
                <div>暂无新闻</div>
            ) : (
                newsList.map(news => (
                    // 必须给列表项加key,避免React警告
                    <div key={news.id}>{news.title}</div>
                ))
            )}
        </div>
    ); 
}

API层优化(可选)

import {News} from '@icofcv/common';
import store from '../store';

function getHeaders() {
    const headers: HeadersInit = {
        'content-type': 'application/json;charset=UTF-8'
    };

    const credentials = store.getState().session.credentials;
    // 简化条件判断,避免重复调用store.getState()
    if (credentials?.accessToken) {
        headers['Authorization'] = `Bearer ${credentials.accessToken}`;
    }

    return headers;
}

export async function getNews(): Promise<News[]>  { 
    const filter = {
        "offset": 0,
        "limit": 100,
        "skip": 0,
        "fields": {
            "id": true,
            "title": true,
            "creationDate": true,
            "enabled": true
        }
    };

    try {
        const response = await fetch(
            `/news?filter=${encodeURIComponent(JSON.stringify(filter))}`,
            { method: "GET", headers: getHeaders() }
        );

        if (!response.ok) {
            // 抛出更详细的错误信息,便于调试
            throw new Error(`请求失败,状态码:${response.status}`);
        }

        const data = await response.json();
        // 确保返回的数据是数组,避免类型错误
        return Array.isArray(data) ? data : [];
    } catch (err) {
        console.error('API请求错误:', err);
        // 重新抛出错误,让上层组件处理
        throw err;
    }
}

关键修复说明

  1. 状态类型修正:移除JSON.stringify(response),直接将API返回的数组存入状态,这样才能用map遍历对象并获取news.title属性。
  2. 初始状态设置:useState([])确保首次渲染时newsList是数组,不会出现undefined.map的错误。
  3. 异步逻辑简化:用await替代.then/.catch,让代码更易读,同时统一错误处理。
  4. 添加加载与错误状态:避免页面空白或报错,提升用户体验。
  5. 列表项key设置:React要求列表项必须有唯一key,这里用news.id符合规范。
  6. API层健壮性优化:添加数组校验、简化header逻辑、抛出详细错误信息,便于调试API访问问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 22:39:17