为什么fetchData
函数定义在useEffect
内部而不是外部?
链接: https://github.com/zeit/next.js/blob/canary/examples/with-graphql-faunadb/lib/useFetch.js
import { useState, useEffect } from 'react'
export default function useFetch(url, options) {
const [data, setData] = useState(null)
const [error, setError] = useState(null)
useEffect(() => {
const fetchData = async () => {
try {
const res = await fetch(url, options)
const json = await res.json()
setData(json)
} catch (error) {
setError(error)
}
}
fetchData()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [url])
return { data, error }
}
我会那样做的:
import { useState, useEffect } from 'react'
export default function useFetch(url, options) {
const [data, setData] = useState(null)
const [error, setError] = useState(null)
// Defined outside of useEffect
// `u` instead of `url` for not overlapping
// with the one passed in useFetch()
const fetchData = async (u) => {
try {
const res = await fetch(u, options)
const json = await res.json()
setData(json)
} catch (error)
setError(error)
}
}
useEffect(() => {
// Using url as an argument
fetchData(url)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [url])
return { data, error }
}
阅读起来似乎更容易,组织起来也更好。我想这可能是反模式或其他?
答案 0 :(得分:1)
我通常在useEffect内定义函数,这有几个原因
例如,在最后一个上,您可以执行一些操作以防止在效果清除时调用状态。
您还可以将AbortController与fetch一起使用来取消提取。
import { useState, useEffect } from 'react'
export default function useFetch(url, options) {
const [data, setData] = useState(null)
const [error, setError] = useState(null)
useEffect(() => {
let isUnmounted = false;
const fetchData = async () => {
try {
const res = await fetch(url, options)
const json = await res.json()
if(!isUnmounted) setData(json)
} catch (error) {
if(!isUnmounted) setError(error)
}
}
fetchData()
return ()=>{isUnmounted = true;}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [url])
return { data, error }
}
答案 1 :(得分:0)
从技术上讲,根据React Hooks规则,fetchData应该是useEffect的依赖项。但是,如果添加了它,它将给您一个错误,指出如果在组件内部定义了此钩子,则在重新创建函数时,useEffect将在每次重新渲染时运行。
但是由于它是在组件外部定义的,所以我的理解是该函数不会被重新创建。然后只需将fetchData添加为依赖项即可。
如果在组件内部使用了useEffect,则可以只在useEffect内传递函数,也可以添加依赖项并使用useCallback覆盖fetchData。