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

React Suspense数据获取:如何将组件Props传入Promise?

解决React Suspense结合props传参的异步数据获取问题

原示例的问题在于用了全局的status和result变量,且请求逻辑在组件外部初始化,无法响应组件props中userId的变化。要解决这个问题,核心是为每个不同的userId维护独立的请求状态与缓存,避免全局变量的冲突。

修改方案

  1. 用缓存映射替代全局变量:创建一个对象存储每个userId对应的请求状态、结果和Promise,确保不同用户的数据互不干扰。
  2. 让fetchPosts根据传入的userId处理缓存逻辑:如果缓存中已有该用户的请求记录,直接复用;没有则发起新请求并更新缓存。
  3. 在组件内部调用fetchPosts:每次组件渲染时,基于当前props的userId获取对应数据。

修改后的完整代码

import React from "react";
import Post from "./Post";

// 为每个userId维护独立的请求缓存,避免全局状态冲突
const postsCache = new Map();

// Posts组件:接收userId作为props
const Posts = ({ userId }) => {
  // 根据当前props的userId获取数据
  const posts = fetchPosts(userId)();
  return (
    <div style={{ display: "flex", flexWrap: "wrap", gap: "10px" }}>
      {posts.map((post, idx) => (
        <Post post={post} key={idx} />
      ))}
    </div>
  );
};

// 带缓存逻辑的异步数据获取函数
function fetchPosts(userId) {
  // 检查缓存中是否已有该userId的请求记录
  if (postsCache.has(userId)) {
    const cacheEntry = postsCache.get(userId);
    return () => {
      if (cacheEntry.status === "pending") {
        throw cacheEntry.fetchPromise; // 触发Suspense
      } else if (cacheEntry.status === "rejected") {
        throw cacheEntry.result; // 抛出错误
      } else {
        return cacheEntry.result; // 返回已获取的数据
      }
    };
  }

  // 没有缓存时,发起新请求
  const cacheEntry = {
    status: "pending",
    result: null,
    fetchPromise: null
  };
  postsCache.set(userId, cacheEntry);

  const url = `https://jsonplaceholder.typicode.com/posts${
    userId ? `?userId=${userId}` : ""
  }`;
  cacheEntry.fetchPromise = fetch(url)
    .then(res => res.json())
    .then(success => {
      cacheEntry.status = "fulfilled";
      cacheEntry.result = success;
    })
    .catch(error => {
      cacheEntry.status = "rejected";
      cacheEntry.result = error;
    });

  // 返回状态检查函数,触发Suspense或返回结果
  return () => {
    if (cacheEntry.status === "pending") {
      throw cacheEntry.fetchPromise;
    } else if (cacheEntry.status === "rejected") {
      throw cacheEntry.result;
    } else {
      return cacheEntry.result;
    }
  };
}

export default Posts;

关键说明

  • postsCache用Map存储,键为userId,值包含该用户请求的状态、结果和Promise,确保每个用户的数据独立。
  • 组件每次渲染时,都会根据当前props的userId调用fetchPosts,自动复用已有缓存或发起新请求。
  • 当userId变化时,组件会触发新的请求,同时Suspense会处理加载状态,无需额外的loading状态管理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 00:03:27