我正在尝试创建一个自定义钩子,并且遇到无限循环问题。
有一段代码实现了我页面上的自定义钩子:
const handleOnFinish = response => {
const {data} = response
setIsLoading(false)
setTableData(data)
setPage(page)
}
const handleOnInit = () => setIsLoading(true)
useEffectUseCaseTokenValidation({
onFinish: handleOnFinish,
onInit: handleOnInit,
params: {nameToFilter: nameFilter, page},
useCase: 'get_clients_use_case'
})
这是我的自定义钩子:
import {useContext, useEffect} from 'react'
import Context from '@s-ui/react-context'
const noop = () => {}
export function useEffectUseCaseTokenValidation({
onFinish = noop,
onInit = noop,
params = {},
useCase = ''
}) {
const {domain} = useContext(Context)
const config = domain.get('config')
useEffect(() => {
onInit()
domain
.get(useCase)
.execute(params)
.then(response => {
const {error} = response
if (error && error.message === 'INVALID_TOKEN') {
window.location.replace(config.get('LOGIN_PAGE_URL'))
}
onFinish(response)
})
}, [params]) // eslint-disable-line
}
这样,useEffect
就会一次又一次地释放,而不是考虑参数。我为参数添加了console.log
,并且总是收到相同的参数。
我在没有自定义钩子的情况下正确使用了useCase
,所以这不是问题。
我想使用此自定义钩子以避免在所有项目页面的所有UseEffects上复制和粘贴重定向。
谢谢!
答案 0 :(得分:1)
问题是对象ref,这意味着您将{nameToFilter: nameFilter, page}
作为参数进行传递,但是每次组件渲染新的对象ref时都在创建,因此,将两者与===
进行比较,如果您可以在控制台中运行此代码
var params1 = { name: 'mike', age: 29 };
var params2 = { name: 'mike', age: 29 };
console.log(params1 === params2); // it will console false
那是因为当对象的键/值对相同时,对象声明不是同一事件。
因此,为避免无限循环进入钩子,应使用useMemo
来避免这种情况,因此请尝试
import { useMemo } from 'react';
const params = useMemo(() => ({ nameToFilter: nameFilter, page }), [nameFilter, page])
useEffectUseCaseTokenValidation({
onFinish: handleOnFinish,
onInit: handleOnInit,
params: params,
useCase: 'get_clients_use_case'
})
useMemo
将避免在组件的每个渲染阶段重新创建对象放样
请阅读useMemo react official docs
请阅读此post,以了解值与引用比较之间的区别