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

React切换/category/:categoryId路由时useEffect不触发请求问题求解

问题根因分析

  1. 路由切换数据不更新:你的useEffect依赖数组为空,仅会在组件首次挂载时执行一次。由于/category/:categoryId复用同一个Categories组件,路由切换时组件不会重新挂载,因此不会触发新的数据请求。
  2. 请求时序异常:这是典型的请求竞态问题,如果前一个分类的接口响应比后一个慢,后发出的请求结果会被先发出的慢请求结果覆盖。

修复方案

1. 核心修改点

  • 将categoryId加入useEffect的依赖数组,只要分类ID变化就自动触发新的请求
  • 新增AbortController取消未完成的请求,解决竞态问题
  • 修正useState的命名规范(你当前的命名是反的,状态变量在前、更新函数在后,避免后续逻辑混淆)

2. 修复后的完整代码

const Categories = () => {
    // 修正useState命名:[状态变量, 更新函数]
    const [products, setProducts] = useState([]);
    const { categoryId } = useParams();

    useEffect(() => {
        // 初始化中断控制器,用于取消未完成的请求
        const controller = new AbortController();
        const signal = controller.signal;

        fetch(`https://fakestoreapi.com/products/category/${categoryId}`, { signal })
            .then(res=>res.json())
            .then(data=>{
                // 只有请求未被中断才更新数据
                if(!signal.aborted){
                    setProducts(data)
                }
            })
            .catch(err=>{
                // 忽略请求中断的报错
                if(err.name !== 'AbortError'){
                    console.error('请求失败:', err)
                }
            })

        // useEffect清理函数:组件卸载/依赖变化时执行,中断上一次的请求
        return () => controller.abort();
    },[categoryId]); // 新增categoryId作为依赖,变化时重新执行effect

    return(
        <div className="container">
            {products.map((p) => (
                <Producto
                    title={p.title}
                    price={p.price}
                    description={p.description}
                    image={p.image}
                    key={p.id}
                    id={p.id}
                />
            ))}
        </div>
    )
}

export default Categories;

路由配置无需修改,上述改动已经可以覆盖你遇到的所有问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 15:48:02