为何配置条件判断的Next.js代码仍持续请求指定接口?
Next.js条件请求失效,接口持续重复调用的原因及修复
这段Next.js代码里,明明配置了条件请求逻辑,但getCategories接口仍被反复调用,核心问题出在条件判断逻辑错误,再加上函数执行时机未合理控制。
问题代码
Home.jsx
import { getCategories } from "@/services/categories"; export default function Home() { const [categories, setCategories] = useState([]); const [subcategories, setSubCategories] = useState([]); const [open, setOpen] = useState(false); const [load, setLoad] = useState(false); const searchParams = useSearchParams(); const loadValue = () => { if (categories.length == undefined) { if (categories.length <= 0) { getCategories() // 此处被循环调用 .then((data) => setCategories(data)) .catch((err) => console.error(err)); } } if (subcategories.length == undefined) { if (subcategories.length <= 0) { getsubcategories() .then((data) => setSubCategories(data)) .catch((err) => console.error(err)); } } };
categories.js
import axios from "axios"; import { url } from "./url.js"; export async function getCategories() { return axios .get(url + "/v1/categories") .then((res) => { return res.data; }) .catch((err) => console.error(err)); }
错误原因
- 条件判断逻辑错误:
categories通过useState([])初始化为空数组,数组的length属性永远是数字类型,不可能为undefined。你写的if (categories.length == undefined)条件永远不成立,但如果loadValue被频繁触发(比如未加依赖的useEffect、重复事件绑定),再加上原本想判断数组为空的逻辑被错误嵌套,最终导致接口被反复调用。 - 函数执行时机失控:如果
loadValue没有被合理限制执行时机(比如组件每次渲染都执行一次),哪怕条件逻辑正确,也会因为状态更新触发重渲染,导致函数反复执行,进而重复调用接口。
修复方案
1. 修正条件判断逻辑
去掉多余的length == undefined判断,直接判断数组是否为空:
const loadValue = () => { // 仅当categories为空数组时调用接口 if (categories.length <= 0) { getCategories() .then((data) => setCategories(data)) .catch((err) => console.error(err)); } // subcategories同理修正 if (subcategories.length <= 0) { getsubcategories() .then((data) => setSubCategories(data)) .catch((err) => console.error(err)); } };
2. 控制函数执行时机
用useEffect限制loadValue仅在组件挂载时执行一次,避免无意义的重复触发:
import { useEffect } from 'react'; // ... 其他组件代码 useEffect(() => { loadValue(); }, []); // 空依赖数组表示仅在组件首次挂载时执行
3. 添加加载状态防止重复请求
避免接口请求未完成时再次触发调用:
const [isLoadingCategories, setIsLoadingCategories] = useState(false); const [isLoadingSubCategories, setIsLoadingSubCategories] = useState(false); const loadValue = () => { if (categories.length <= 0 && !isLoadingCategories) { setIsLoadingCategories(true); getCategories() .then((data) => setCategories(data)) .catch((err) => console.error(err)) .finally(() => setIsLoadingCategories(false)); } if (subcategories.length <= 0 && !isLoadingSubCategories) { setIsLoadingSubCategories(true); getsubcategories() .then((data) => setSubCategories(data)) .catch((err) => console.error(err)) .finally(() => setIsLoadingSubCategories(false)); } };
内容的提问来源于stack exchange,提问作者riki
相关产品推荐
相关产品推荐

