在React Remix中使用Fetcher实现数据加载更多的正确方式
在Remix中实现产品列表加载更多的正确方式
你的代码核心问题是:使用fetcher.load发起加载更多请求后,没有读取fetcher返回的新数据来更新列表——useLoaderData只会拿到页面初始加载的数据,不会自动同步fetcher请求的结果。另外你的loader还有参数解构错误,先一步步修复:
1. 修复Loader的基础错误
原loader里没有解构request参数,导致request.url会报错,同时要把offset转为数字类型避免接口出错:
export async function loader({ request, context }: LoaderFunctionArgs) { const url = new URL(request.url); const offset = Number(url.searchParams.get("offset")) || 0; const { products, count } = await getProducts({ limit: 10, offset, }); return { products, totalCount: count.aggregate?.count, }; }
2. 正确处理Fetcher加载的新数据
在组件中需要从fetcher.data获取新加载的产品,合并到现有列表,同时处理加载状态和重复请求:
export default function UploadProductsRoute() { const { products: initialProducts, totalCount } = useLoaderData<typeof loader>(); const fetcher = useFetcher(); const fetchers = useFetchers(); // 处理表单提交的乐观更新数据 const optimisticProducts = fetchers.reduce<typeof initialProducts>((memo, f) => { if (f.formData) { const data = Object.fromEntries(f.formData) as typeof initialProducts[0]; // 避免重复添加已存在的产品 if (!memo.some(item => item.id === data.id) && !initialProducts.some(item => item.id === data.id)) { memo.push(data); } } return memo; }, []); // 合并初始数据、乐观更新数据、加载更多的新数据 let products = [...initialProducts, ...optimisticProducts]; if (fetcher.data && fetcher.data.products) { // 过滤重复项,避免乐观更新后fetcher返回重复数据 const newProducts = fetcher.data.products.filter( item => !products.some(p => p.id === item.id) ); products = [...products, ...newProducts]; } // 判断是否还有更多数据可加载 const hasMore = products.length < (totalCount || 0); // 加载状态判断 const isLoading = fetcher.state === "loading"; return ( <div> <div> <div> <h1>添加产品</h1> </div> <AddProductForm /> <div> <h1>已添加的产品</h1> </div> <div> <div> {products.map((product) => ( <ProductItem key={product.id} name={product.name} description={product.description} /> ))} {/* 加载中提示 */} {isLoading && <div>加载中...</div>} </div> </div> <div> {/* 仅当有更多数据且未加载时显示按钮 */} {hasMore && !isLoading && ( <Button onClick={() => { fetcher.load(`?offset=${products.length}`); }}> 加载更多 </Button> )} </div> </div> </div> ); }
关键修复点说明
- 读取fetcher.data:
fetcher.load请求完成后,新数据会存在fetcher.data中,需要手动合并到现有列表。 - 避免重复数据:不管是乐观更新还是加载更多,都要过滤已存在的产品,防止列表出现重复项。
- 加载状态控制:通过
fetcher.state判断加载状态,禁用按钮或显示提示,避免重复请求。 - 是否还有更多数据:用当前列表长度和总产品数对比,决定是否显示「加载更多」按钮。
内容的提问来源于stack exchange,提问作者Joseph
相关产品推荐
相关产品推荐

