在 useEffect 内部或外部定义函数?
Posted
技术标签:
【中文标题】在 useEffect 内部或外部定义函数?【英文标题】:Define a function inside useEffect or outside? 【发布时间】:2020-08-15 01:53:12 【问题描述】:为什么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
它似乎更易于阅读且更有条理。我在想这可能是一种反模式或其他什么?
【问题讨论】:
我在 React 文档中找到了我的答案:fr.reactjs.org/docs/… 【参考方案1】:根据 React Hooks 规则,从技术上讲 fetchData 应该是 useEffect 的依赖项。但是如果你添加它,它会给你一个错误,说它会导致 useEffect 在每次重新渲染时运行,因为如果这个钩子是在组件中定义的,则重新创建函数。
但是由于它是在组件之外定义的,所以我的理解是不会重新创建该函数。然后只需将 fetchData 添加为依赖项。
如果这个 useEffect 在组件中使用,您可以只在 useEffect 中传递函数,或者添加依赖项并使用 useCallback 覆盖您的 fetchData。
【讨论】:
【参考方案2】:我通常在 useEffect 中定义函数,有几个原因
-
通过在使用效果之外定义函数,您要么需要禁用详尽的deps,否则会冒着意外获得陈旧函数的风险,或者需要使用回调使函数在每次渲染时都不更新
如果该函数仅用于 useEffect 中,则无需在每次渲染时重新创建该函数,因为这只是浪费循环
通过在 useEffect 中定义异步函数,可以更轻松地对异步函数进行清理,因为您可以定义能够在效果中修改的变量。
例如,在最后一个上,您可以执行一些操作来防止在清理效果时调用状态。
您也可以使用带有 fetch 的 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
【讨论】:
以上是关于在 useEffect 内部或外部定义函数?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 useEffect 之外的函数被调用,而没有依赖数组的 useEffect 内部的函数却没有?
安装jmeter 环境变量都配置好了 可还是出现不是内部外部命令
无效的挂钩调用。钩子只能在反应函数组件内部使用...... useEffect,redux
react ESlint警告: React Hook useEffect has a missing dependency