在 useEffect 中替代自定义挂钩调用
Alternative to custom hook call inside useEffect
我有当前组件:
const Timeline = ({ threshold, throttle }) => {
const [films, setFilms] = useState([])
const [page, setPage] = useState(1)
const [loadMoreLock, setLoadMoreLock] = useState(false)
const [
localStorageFilmsCache,
setLocalStorageFilmsCache
] = useLocalStorage('filmsCache', films);
useEffect(() => {
const fetchFilms = async () => {
try {
const res = await fetch(
`${API_PATH_BASE}/${API_VERSION}/${TRENDING_ENDPOINT}/movie/week?api_key=${THE_MOVIE_DB_API_KEY}&page=${page}`, {
method: 'GET',
}
)
const json = await res.json()
if (page === 1) {
setFilms((films) => json.results)
} else {
setFilms((films) => ([
...films,
...json.results,
]))
}
setLoadMoreLock(() => false)
} catch (e) {
setFilms(() => null)
}
}
if (!loadMoreLock) {
fetchFilms()
}
// Scroll handler fns...
}, [page, loadMoreLock, threshold, throttle])
// Return JSX..
还有一个自定义挂钩:
const useLocalStorage = (key, initialValue = '') => {
const [storedValue, setStoredValue] = useState(() => {
try {
const currValue = window.localStorage.getItem(key)
return currValue ? JSON.parse(currValue) : initialValue
} catch (e) {
return initialValue
}
})
const setValue = (value) => {
try {
const valueToStore = value instanceof Function
? value(storedValue)
: value
setStoredValue(() => valueToStore)
window.localStorage.setItem(key, JSON.stringify(valueToStore))
} catch (e) {}
}
return [
storedValue,
setValue,
]
}
我想使用我的 localStorage 自定义挂钩为 API 调用构建客户端缓存。在当前上下文中,我将不得不在默认 fn useEffect 中使用我的自定义挂钩(状态和 setter fn)作为参数接收,这是不可能的。我对钩子很陌生,而且我很难考虑替代方案。我可以在没有 localStorage 挂钩的情况下执行此操作,但如果能重新使用我已经掌握的逻辑会很好。
谢谢!
您可以在没有钩子的情况下重用您的函数。如果您希望数据具有反应性,钩子很重要。您的样本不需要是反应性的。如果您确实希望数据具有反应性,则当前实施无效,因为您需要 useContext
.
目前您的 useLocalStorage
获取或设置值 localStorage
。您的 useState
无关紧要,因为您可以直接 return 该值并将其存储在您的其他 useState
中(电影、页面等)。如果您试图减少对 localStorage
的调用,这仍然是无关紧要的,因为对于使用 useLocalStorage
的每个组件,它都会从 localStorage
重复加载。您可以通过在 storedValue
的 useState
初始化函数中插入 console.log 语句来测试它。 React context
会调用一次并将其提供给所有组件。
我有当前组件:
const Timeline = ({ threshold, throttle }) => {
const [films, setFilms] = useState([])
const [page, setPage] = useState(1)
const [loadMoreLock, setLoadMoreLock] = useState(false)
const [
localStorageFilmsCache,
setLocalStorageFilmsCache
] = useLocalStorage('filmsCache', films);
useEffect(() => {
const fetchFilms = async () => {
try {
const res = await fetch(
`${API_PATH_BASE}/${API_VERSION}/${TRENDING_ENDPOINT}/movie/week?api_key=${THE_MOVIE_DB_API_KEY}&page=${page}`, {
method: 'GET',
}
)
const json = await res.json()
if (page === 1) {
setFilms((films) => json.results)
} else {
setFilms((films) => ([
...films,
...json.results,
]))
}
setLoadMoreLock(() => false)
} catch (e) {
setFilms(() => null)
}
}
if (!loadMoreLock) {
fetchFilms()
}
// Scroll handler fns...
}, [page, loadMoreLock, threshold, throttle])
// Return JSX..
还有一个自定义挂钩:
const useLocalStorage = (key, initialValue = '') => {
const [storedValue, setStoredValue] = useState(() => {
try {
const currValue = window.localStorage.getItem(key)
return currValue ? JSON.parse(currValue) : initialValue
} catch (e) {
return initialValue
}
})
const setValue = (value) => {
try {
const valueToStore = value instanceof Function
? value(storedValue)
: value
setStoredValue(() => valueToStore)
window.localStorage.setItem(key, JSON.stringify(valueToStore))
} catch (e) {}
}
return [
storedValue,
setValue,
]
}
我想使用我的 localStorage 自定义挂钩为 API 调用构建客户端缓存。在当前上下文中,我将不得不在默认 fn useEffect 中使用我的自定义挂钩(状态和 setter fn)作为参数接收,这是不可能的。我对钩子很陌生,而且我很难考虑替代方案。我可以在没有 localStorage 挂钩的情况下执行此操作,但如果能重新使用我已经掌握的逻辑会很好。 谢谢!
您可以在没有钩子的情况下重用您的函数。如果您希望数据具有反应性,钩子很重要。您的样本不需要是反应性的。如果您确实希望数据具有反应性,则当前实施无效,因为您需要 useContext
.
目前您的 useLocalStorage
获取或设置值 localStorage
。您的 useState
无关紧要,因为您可以直接 return 该值并将其存储在您的其他 useState
中(电影、页面等)。如果您试图减少对 localStorage
的调用,这仍然是无关紧要的,因为对于使用 useLocalStorage
的每个组件,它都会从 localStorage
重复加载。您可以通过在 storedValue
的 useState
初始化函数中插入 console.log 语句来测试它。 React context
会调用一次并将其提供给所有组件。