使用React Suspense与Await无法正常获取数据的技术问题
问题解决:使用和时仅获取到Response对象
你的核心问题是getBookmarks函数直接返回了fetch的Response对象,而非解析后的实际业务数据。
问题根源
fetch API调用成功后返回的是Response实例,它仅包含响应头、状态码等元数据,实际的业务数据存储在响应体中。当你仅用useLoaderData时,可能后续代码中手动做了解析操作;但使用defer配合Await时,Await会直接将Promise的最终结果(未解析的Response)传递给渲染函数,所以你看到的是Response对象而非期望的数据。
修复步骤
修改api.js中的数据解析逻辑
在getBookmarks函数中添加响应体解析步骤(假设接口返回JSON格式数据):import config from './config' const apiUrl = config.apiUrl; const apiPort = config.apiPort; const joinUrl = (baseUrl, url) => { return `${baseUrl}/${url}` } const domain = `${apiUrl}:${apiPort}/api/bookmarks`; export async function getBookmarks(url = "") { url = joinUrl(domain, url) const response = await fetch(url); // 校验响应状态,提前捕获请求失败场景 if (!response.ok) { throw new Error(`请求失败:${response.status}`); } // 解析JSON响应体,返回实际业务数据 return await response.json(); }调整Home.jsx的渲染逻辑(可选)
现在renderBookMarks接收的是解析后的业务数据,可以直接渲染:import React, { Suspense } from "react"; import { getBookmarks } from "./api"; import { useLoaderData, defer, Await } from "react-router-dom"; export function loader() { return defer({ bookmarks: getBookmarks() }); } export default function Home() { const dataPromise = useLoaderData(); function renderBookMarks(bookmarks) { console.log(bookmarks); // 现在打印的是解析后的业务数据 return ( <ul className="bookmarks-list"> {bookmarks.map(bookmark => ( <li key={bookmark.id}>{bookmark.title}</li> ))} </ul> ); } return ( <div> <h2>Welcome to bookmarks</h2> <Suspense fallback={<h2>Loading...</h2>}> <Await resolve={dataPromise.bookmarks}> {renderBookMarks} </Await> </Suspense> </div> ) }
补充说明
- 如果接口返回文本格式数据,可将
response.json()替换为response.text(); - 添加
response.ok校验能避免后续渲染逻辑处理无效的失败请求数据。
内容的提问来源于stack exchange,提问作者manjosh
相关产品推荐
相关产品推荐

