将自定义useApi钩子移入Auth组件后调用出现无限API请求循环
问题根因
- 组件调用方式错误:你在Main.tsx的逻辑中直接调用
Auth()而非以JSX形式<Auth />渲染组件,不符合React组件运行规则。直接调用函数式组件时,React不会为其维护独立的组件生命周期和状态存储,每次Main组件重渲染都会完全重新执行Auth函数的所有逻辑,包括重新初始化所有useState、重新调用useApi,相当于每次都生成全新的钩子实例,这是无限请求的核心诱因之一。 - 传入useApi的参数引用不稳定:你直接在Auth组件内部声明的
opts、defaultPayload都是普通对象,内部的fail、callback也是每次渲染都会重新生成的箭头函数,没有做引用稳定处理。每次Auth执行时这些参数都是全新的引用,而useApi内部的go函数用了useCallback且依赖payload,还有监听payload变化的useEffect,只要参数引用变化就会触发钩子逻辑重新执行,发起新的API请求。
对比你之前直接在Main里调用useApi的场景:Main里的payload是通过useState创建的,引用默认是稳定的,不会每次渲染都变化,所以不会触发多余的执行。
修复步骤
- 修正组件调用方式:在Main组件的返回JSX中使用
<Auth />渲染组件,不要在顶层逻辑直接调用Auth():
// Main.tsx 修正后 function Main():JSX.Element { // 其他逻辑不变 return ( {/* 其他组件内容 */} <Auth /> ) }
- 稳定Auth组件内的参数引用:用
useCallback包裹函数,用useMemo包裹对象,确保依赖不变时引用不变:
// Auth.tsx 修正后 function Auth():JSX.Element{ const [username, setUsername] = useState('') const [password, setPassword] = useState('') // 稳定fail函数引用 const fail = useCallback(() => null, []) // 稳定opts对象引用 const opts = useMemo(() => ({ username: username, password: password, fail: fail, }), [username, password, fail]) // 稳定callback函数引用 const callback = useCallback(() => null, []) // 稳定payload对象引用 const defaultPayload = useMemo(() => ({ path:'notes/validateAuth/', method: 'GET', body: null, callback: callback }), [callback]) useApi(opts, defaultPayload) return <></> }
- 可选优化useApi内部依赖:可以将
go函数依赖的payload字段拆包,只依赖实际用到的path、method、body、callback,避免payload其他无关字段变化导致不必要的函数重建。
内容的提问来源于stack exchange,提问作者Raven
相关产品推荐
相关产品推荐

