如何将Axios实现的购物车逻辑迁移至useSWR?
解决useSWR迁移后购物车数据不返回的问题
问题分析
你当前的useSWR实现只覆盖了登录用户的部分逻辑,且存在几个关键问题导致数据无法返回:
- 未处理访客用户(无token)的购物车流程
- 依赖请求的触发条件不匹配原逻辑(原Axios中登录用户POST创建后,GET的URL是
apis.create_cart,而非apis.get_cart) - Fetcher函数未正确绑定依赖(token变化时未重新触发请求)
- 未将最终获取的购物车数据返回给组件使用
修正后的完整实现
以下是完全对齐原Axios逻辑的useSWR版本,包含登录/访客两种场景的处理:
import useSWR from 'swr'; import axios from 'axios'; // 封装通用fetcher,支持POST/GET请求,兼容带token的场景 const fetcher = async ({ url, method = 'GET', headers = {}, data = null }) => { try { const res = await axios({ url, method, headers, data }); return res.data; } catch (err) { throw err.response?.data || err.message; } }; export function useCart(logged, token, apis) { // -------------------------- // 登录用户逻辑:先创建购物车,再获取购物车数据 // -------------------------- const { data: createCartRes, error: createCartErr } = useSWR( logged && token ? { url: apis.create_cart, method: 'POST', headers: { Authorization: `Bearer ${token}` } } : null, fetcher ); const { data: cartData, error: getCartErr } = useSWR( // 仅当创建购物车请求完成后,才触发获取请求 createCartRes && logged && token ? { url: apis.create_cart, headers: { Authorization: `Bearer ${token}` } } : null, fetcher ); // -------------------------- // 访客用户逻辑:处理guest_cart_id // -------------------------- const guestCartId = typeof window !== 'undefined' ? window.localStorage.getItem('guest_cart_id') : null; // 创建访客购物车(仅当无guestCartId时触发) const { data: createGuestCartRes, error: createGuestCartErr } = useSWR( !logged && !token && !guestCartId ? { url: apis.create_guest_cart, method: 'POST' } : null, fetcher, { onSuccess: (data) => { // 创建成功后存入localStorage if (typeof window !== 'undefined') { window.localStorage.setItem('guest_cart_id', data); } } } ); // 获取访客购物车数据 const targetGuestCartId = createGuestCartRes || guestCartId; const { data: guestCartData, error: getGuestCartErr } = useSWR( !logged && !token && targetGuestCartId ? { url: `${apis.get_guest_cart}/${targetGuestCartId}/items` } : null, fetcher ); // 合并两种场景的最终数据 const finalCartData = logged ? cartData : guestCartData; const finalError = createCartErr || getCartErr || createGuestCartErr || getGuestCartErr; const isLoading = !finalCartData && !finalError; return { cart: finalCartData, isLoading, error: finalError }; }
关键修正点说明
- 统一Fetcher:封装支持POST/GET的通用fetcher,避免重复代码,同时兼容Axios(和原实现一致,降低迁移成本)
- 依赖请求触发:登录用户的获取购物车请求,仅在
createCartRes存在时触发,确保先完成创建操作 - 访客逻辑补全:完整实现访客购物车的创建、存储、获取流程,和原Axios逻辑对齐
- 数据合并返回:根据
logged状态返回对应场景的购物车数据,同时提供loading和error状态供组件使用 - SSR兼容:添加
typeof window !== 'undefined'判断,避免在服务端渲染时访问localStorage报错
使用方式
在组件中直接调用该hook即可:
const { cart, isLoading, error } = useCart(logged, token, apis); if (isLoading) return <div>加载中...</div>; if (error) return <div>加载失败:{error.message}</div>; // 使用cart数据 return <div>购物车商品:{cart?.length || 0}件</div>;
内容的提问来源于stack exchange,提问作者Mohammed Ismail
相关产品推荐
相关产品推荐

