自定义钩子的Useeffect依赖项列表警告

时间:2019-10-19 09:41:03

标签: reactjs react-hooks

因此,我正在构建一个React应用,并且试图简化使用axios的自定义挂钩调用后端api的过程。这个钩子保持加载和错误状态,因此我不必在发出请求的每个组件中都保持该状态。它还公开了一个callApi()函数,该函数发出实际请求,然后更改挂钩中的状态。这是自定义钩子的代码。

import { useState } from 'react'
import axios, { AxiosRequestConfig } from 'axios'

export default <DataType>() => {
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState('')
  const [data, setData] = useState<DataType>()

  async function callApi(config: AxiosRequestConfig) {
    setLoading(true)
    setError('')
    try {
      const response = await axios.request<DataType>(config)
      setData(response.data)
    } catch (error) {
      if (error.response) setError(error.response.data.msg)
      else if (error.request) setError('A network error occured')
      else setError('An error occured')
    } finally {
      setLoading(false)
    }
  }

  return {
    data,
    loading,
    error,
    callApi
  }
}

然后我尝试在要发出请求的组件的useEffect挂钩中使用此callApi()方法。

const { data: posts, loading, error, callApi } = useApi<Post[]>()

  useEffect(() => {
    callApi({
      url: 'http://localhost:4000/blog'
    })
  }, [])

这可以按预期工作,但是我的linter(使用create-react-app设置)发出了以下警告:

  

React Hook useEffect缺少依赖项:'callApi'。包括它或删除依赖项数组react-hooks / exhaustive-deps   如果我将callApi添加到依赖项数组或完全删除依赖项数组,则会创建一个无限循环,因为callApi会更新状态,而我只想在安装时调用api。

如果我删除依赖项列表或将callApi添加到依赖项列表,则将一直在无限循环中调用效果,而我只想在mount上调用。

该警告应如何解决?代码是否存在任何风险(毕竟,短绒猫抱怨是有原因的)?

2 个答案:

答案 0 :(得分:0)

您的useEffect使用自定义钩子返回的callApi函数。

由于函数可以随组件中的任何道具或状态发生变化,因此React警告您,如果函数会发生变化,则永远不会调用新函数。

如果要消除警告,则应将函数添加到第二个参数数组中。

useEffect(() => {
    callApi({
      url: 'http://localhost:4000/blog'
    })
  }, [ callApi ])

答案 1 :(得分:0)

这应该有效:

const callApi = useCallback(async (config: AxiosRequestConfig) => {
  setLoading(true)
  setError('')
  try {
    const response = await axios.request<DataType>(config)
    setData(response.data)
  } catch (error) {
    if (error.response) setError(error.response.data.msg)
    else if (error.request) setError('A network error occured')
    else setError('An error occured')
  } finally {
    setLoading(false)
  }
}), [])

...和...

useEffect(() => {
  callApi({
    url: 'http://localhost:4000/blog'
  })
}, [callApi])

callApi永不更改,因此将其传递给useEffect将具有与useEffect(..., [])相同的行为