React Suspense:如何向函数组件外的fetch传递动态参数?
React Suspense 结合动态ID获取数据的解决方案
核心思路是将数据获取逻辑封装为接收动态ID参数的工厂函数,在组件内部拿到ID后再调用该函数,利用Suspense捕获异步请求的Promise,以此解决外部无法获取动态参数的问题。
修改后的代码示例
Screen.js(无需调整,保持原结构即可)
import { Suspense } from 'react'; import ProductDetailScreen from './ProductDetail'; import Spinner from './Spinner'; export default function Screen() { return ( <Suspense fallback={<Spinner />}> <ProductDetailScreen /> </Suspense> ); }
ProductDetail.js
import { useRoute } from '@react-navigation/native'; import axios from 'axios'; // 替换为你实际使用的请求库 // 缓存已请求的商品数据,避免重复发起相同请求 const productCache = new Map(); // 接收商品ID的工厂函数,处理数据获取与Suspense触发逻辑 function getProductData(productId) { // 检查缓存中是否已有该商品的请求记录 if (productCache.has(productId)) { const cacheItem = productCache.get(productId); // 数据已加载完成,直接返回 if (cacheItem.status === 'resolved') { return cacheItem.value; } // 请求正在进行中,抛出Promise让Suspense捕获 throw cacheItem.promise; } // 无缓存记录,发起新请求 const requestPromise = axios.get(`/api/products/${productId}`) .then(res => { // 请求成功,更新缓存为已完成状态 productCache.set(productId, { status: 'resolved', value: res.data }); return res.data; }) .catch(err => { // 请求失败,更新缓存为错误状态 productCache.set(productId, { status: 'rejected', value: err }); throw err; }); // 将正在进行的请求存入缓存 productCache.set(productId, { status: 'pending', promise: requestPromise }); // 抛出Promise,触发Suspense的fallback显示 throw requestPromise; } export default function ProductDetailScreen() { // 通过useRoute获取路由参数中的商品ID const route = useRoute(); const { productId } = route.params; // 调用带动态ID的获取函数,Suspense会自动处理加载状态 const productData = getProductData(productId); return ( <View> <Text>{productData.name}</Text> <Text>{productData.description}</Text> {/* 其他商品详情UI */} </View> ); }
关键说明
- 缓存机制:用
Map存储每个商品ID的请求状态(pending/resolved/rejected),避免重复请求同一商品,同时处理请求失败的场景。 - 动态参数传递:在组件内部通过
useRoute拿到商品ID后,再调用数据获取函数,完美解决Suspense要求外部执行fetch时无法获取动态参数的问题。 - Suspense触发逻辑:当
getProductData抛出Promise时,Suspense会自动显示fallback组件,直到Promise resolve后再渲染商品详情内容。
内容的提问来源于stack exchange,提问作者Linh Ha
相关产品推荐
相关产品推荐

