4

我已经实现了一个自定义useFetch钩子,所以在我的应用程序中获取:

import { useEffect, useState } from 'react'

const useFetch = ({ url, defaultData = null }) => {
  const [data, setData] = useState(defaultData)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState(null)

  useEffect(() => {
    fetch(url)
      .then(res => res.json())
      .then(res => {
        setData(res)
        setLoading(false)
      })
      .catch(err => {
        setError(err)
        setLoading(false)
      })
  }, [])

  return [data, loading, error]
}

export default useFetch

然后我突然想到......这将在整个应用程序中使用。它如何知道哪个数据/加载/错误属于哪个调用?当我useFetch第一次使用,然后在应用程序的其他地方紧随其后,React 是否会跟踪哪些内部状态变量属于哪个钩子调用?

然后我想也许我需要沿着 Redux 线做更多的事情,并在钩子的帮助下自己跟踪对自定义钩子的所有调用useReducer

import { useEffect, useReducer } from 'react'

const reducer = (state, action) => {
  const { url, data, err } = action
  const currentState = state[url]

  switch (action.type) {
    case 'fetching':
      return { ...state, [url]: { ...currentState, loading: true } }
    case 'success':
      return { ...state, [url]: { ...currentState, loading: false, data } }
    case 'fail':
      return { ...state, [url]: { ...currentState, loading: false, err } }
    default:
      return state
  }
}

const useFetch = ({ url, defaultData = null }) => {
  const [state, dispatch] = useReducer(reducer, {}, { type: 'fetching', url })
  const { data: d, loading: l, err: e } = state[url]

  useEffect(() => {
    fetch(url)
      .then(res => res.json())
      .then(data => dispatch({ type: 'success', url, data }))
      .catch(err => dispatch({ type: 'fail', err }))
  }, [])

  return [d || defaultData, l, e]
}

export default useFetch

我是否需要像第二个示例中那样手动跟踪对useFetch自己的所有呼叫?还是 React 在其内部处理这个问题,而我只需要第一个示例?

4

2 回答 2

2

每个自定义钩子都有自己的状态,并且不会在同一钩子的不同实例之间共享状态。因此,您不需要跟踪哪个状态属于哪个钩子。

Hooks 只会在不同的实例之间共享逻辑而不是数据,就像HOCs and Render Props.

所以第一个例子可以正常工作。

在您的情况下,多次调用useFetch本质上会导致多次调用,useState并且React 常见问题解答解释了状态的独立性,useState它确实回答了您的疑问

React 跟踪当前呈现的组件。由于 Hooks 的规则,我们知道 Hooks 只能从 React 组件调用(或自定义 Hooks——也只能从 React 组件调用)。

每个组件都有一个内部“存储单元”列表。它们只是 JavaScript 对象,我们可以在其中放置一些数据。当你调用 useState() 之类的 Hook 时,它会读取当前单元格(或在第一次渲染期间对其进行初始化),然后将指针移动到下一个单元格。这就是多个 useState() 调用各自获取独立本地状态的方式。

于 2018-11-20T05:05:17.357 回答
1

我写了一个很好的例子,说明你可以在我的包use-httpuseFetch中为更健壮的钩子做些什么

于 2019-05-02T18:20:41.903 回答