gpt4 book ai didi

reactjs - 当依赖是一个函数时,如何避免 useEffect 中的无限更新

转载 作者:行者123 更新时间:2023-12-05 01:53:18 26 4
gpt4 key购买 nike

一个钩子(Hook)正在检查,如果在存储中持久存在模拟信息,页面何时呈现,如果是,则在全局 AppState 上下文中设置这些信息。

const impersonateStorageKey = `impersonation_${config.environment}`
// signature const impersonate: (empScope: number) => void
const { currentImpersonation, impersonate } = useAppContext()

useEffect(() => {
if (!window || !window.localStorage) return;

const storageString = localStorage.getItem(impersonateStorageKey)
if (!storageString) return;

const data = JSON.parse(storageString)
impersonate(data.currentImpersonation)
}, [impersonateStorageKey])

使用第二个钩子(Hook),将当前模拟身份的更改持久保存到存储中:

useEffect(() => {
if (!window || !window.localStorage) return;
localStorage.setItem(impersonateStorageKey, JSON.stringify({ /* ... */}))
}, [currentImpersonation, impersonateStorageKey])

加上来自 useAppContext

的相关位
const useAppContext = () => {
const { state, dispatch } = useContext(AppContext)
if (!state) {
throw new Error("useAppContext must be used within within AppContextProvider")
}

const impersonate = (employeeScope: string | number) => dispatch({ type: 'IMPERSONATE', value: employeeScope })
const currentImpersonation = state.currentImpersonation

return {
impersonate,
currentImpersonation,
}
}

这正常工作,但 linter 提示,第一个 useEffect 钩子(Hook)中缺少依赖模拟

当我将 impersonate 添加到依赖项数组时,这将导致持续更新循环并使应用程序无响应。

我知道是什么导致了这种行为,但我没有看到关于如何打破循环的解决方案(除了忽略规则)让 linter 快乐。

在这里我可以采取哪些方法?

最佳答案

您可以在使用 useCallback 创建函数时内存该函数:

const useAppContext = () => {
const { state, dispatch } = useContext(AppContext)

const impersonate = useCallback(
(employeeScope: string | number) => dispatch({
type: 'IMPERSONATE',
value: employeeScope
}), [dispatch])

if (!state) {
throw new Error("useAppContext must be used within within AppContextProvider")
}

const currentImpersonation = state.currentImpersonation

return {
impersonate,
currentImpersonation,
}
}

如果不能,解决方法是将函数放在 ref 中. ref 是对对象的不可变引用,具有可变的 current 属性。由于 ref 本身是不可变的,您可以将它用作依赖项而不会导致 useEffect 激活(linter 知道它,您甚至不需要将其声明为一个依赖)。您可以随心所欲地改变 current

const impersonateRef = useRef(impersonate)

useEffect(() => {
impersonateRef.current = impersonate
}, [impersonate])

useEffect(() => {
if (!window || !window.localStorage) return

const storageString = localStorage.getItem(impersonateStorageKey)
if (!storageString) return

const data = JSON.parse(storageString)
impersonateRef.current(data.currentImpersonation)
}, [impersonateStorageKey])

关于reactjs - 当依赖是一个函数时,如何避免 useEffect 中的无限更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71124468/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com