React切换/category/:categoryId路由时useEffect不触发请求问题求解
问题根因分析
- 路由切换数据不更新:你的
useEffect依赖数组为空,仅会在组件首次挂载时执行一次。由于/category/:categoryId复用同一个Categories组件,路由切换时组件不会重新挂载,因此不会触发新的数据请求。 - 请求时序异常:这是典型的请求竞态问题,如果前一个分类的接口响应比后一个慢,后发出的请求结果会被先发出的慢请求结果覆盖。
修复方案
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
相关产品推荐
相关产品推荐

