RTK Query请求报错时react-toastify重复弹出Toast的解决方法
问题:RTK Query请求错误时Toast重复弹出的解决方法
使用RTK Query获取数据时,请求出错后通过react-toastify弹出的提示会重复出现,控制台显示错误判断的代码段多次执行,如何阻止Toast重复弹出?
相关代码:
import FoodBox from "../components/FoodBox"; import styled from "styled-components"; import { useFetchFoodsQuery } from "../store"; import { useSelector } from "react-redux"; import Skeleton from "./Skeleton"; import { toast } from "react-toastify"; const Foods = styled.div` overflow-y: auto; overflow-x: hidden; height: 370px; padding: 0 30px; `; function FoodList({ shopId }) { let { data: foods, error, isFetching } = useFetchFoodsQuery(shopId); const user = useSelector((state) => state.user.currentUser); let content; if (isFetching) { content = ( <Foods> <Skeleton w="22.5rem" h="3.5rem" times={5} /> </Foods> ); } else if (error) { toast('Error'); return <div>Error in loading food</div>; } else { if (!user) { foods = foods?.filter((food) => food.isVisible); } content = ( <Foods> {foods?.map((food) => ( <FoodBox key={food?._id} food={food} /> ))} </Foods> ); } return content; } export default FoodList;
核心原因
组件因shopId变化、user状态更新等原因重新渲染时,只要error状态存在,toast('Error')就会重复执行,导致多次弹出提示。
解决办法
方法1:用useEffect监听error变化,仅首次触发Toast
利用React的useEffect钩子,仅在error从无到有发生变化时调用toast,避免重复触发:
import FoodBox from "../components/FoodBox"; import styled from "styled-components"; import { useFetchFoodsQuery } from "../store"; import { useSelector } from "react-redux"; import Skeleton from "./Skeleton"; import { toast } from "react-toastify"; import { useEffect } from "react"; // 引入useEffect const Foods = styled.div` overflow-y: auto; overflow-x: hidden; height: 370px; padding: 0 30px; `; function FoodList({ shopId }) { let { data: foods, error, isFetching } = useFetchFoodsQuery(shopId); const user = useSelector((state) => state.user.currentUser); let content; // 新增:仅在error状态变化时触发一次Toast useEffect(() => { if (error) { toast('Error'); } }, [error]); if (isFetching) { content = ( <Foods> <Skeleton w="22.5rem" h="3.5rem" times={5} /> </Foods> ); } else if (error) { return <div>Error in loading food</div>; } else { if (!user) { foods = foods?.filter((food) => food.isVisible); } content = ( <Foods> {foods?.map((food) => ( <FoodBox key={food?._id} food={food} /> ))} </Foods> ); } return content; } export default FoodList;
方法2:给Toast设置唯一ID,避免重复显示
react-toastify支持通过toastId指定唯一标识,相同ID的Toast不会重复弹出:
// 修改error分支的toast调用 else if (error) { toast('Error', { toastId: 'food-fetch-error' }); // 固定唯一ID return <div>Error in loading food</div>; }
方法3:结合RTK Query的isError状态(可选)
RTK Query的查询钩子返回isError布尔值,可配合useEffect使用,逻辑更直观:
let { data: foods, error, isFetching, isError } = useFetchFoodsQuery(shopId); // 配合useEffect触发Toast useEffect(() => { if (isError) { toast('Error'); } }, [isError]);
注意事项
- 优先选择方法1,能精准监听
error变化,避免不必要的Toast触发; - 方法2适合简单场景,若需区分不同错误,需调整
toastId; - 当
shopId变化触发新请求时,新的错误应重新触发Toast,这属于合理行为,无需额外处理。
内容的提问来源于stack exchange,提问作者Het Patel
相关产品推荐
相关产品推荐

