关于 useEffect 重复调用以及依赖数组的问题?
关于`useEffect`有有一些疑惑疑惑, 如下, 代码已经放入codesandbox 的 CounterHook.js 文件中
代码简化如下:
```
const CounterHook = props => {
  const [count, setCount] = useState(0)
  const [loading, setLoading] = useState(false)

  useEffect(() => {
    setLoading(true)
    console.log(loading) // false, true, false, ture...
    // 模拟发送数据
    setTimeout(() => {
      setLoading(false)
      setCount(1)
    }, 2000)
  })
  
  return ...
}
```
这里如果没有添加`useEffect`的依赖数组, 会造成无限循环. 不是特别理解为什么会造成无限循环. 个人打印了一下 loading, 发现一直不断重复输出 false, true, false, true....
### 第一个问题
个人对造成无限循环的理解:
- 在调用`useEffect`之前, loading 是 false
- 
第一次调用`useEffect`:

类似`componentDidMount`, 此时 loading 被设置成了 true, 同时发出了一个异步请求
请求结束, loading 又被设置成了 false, 组件的 state 被更新了, 由于 `useEffect` 在组件更新更新时也会触发, 因此触发第二次`useEffect`:


- 第二次调用`useEffect`: 和第一次一样, 首先`componentDidMount`, 设置 loading 为 true...循环继续
第一次调用`useEffect`:
- 类似`componentDidMount`, 此时 loading 被设置成了 true, 同时发出了一个异步请求
- 请求结束, loading 又被设置成了 false, 组件的 state 被更新了, 由于 `useEffect` 在组件更新更新时也会触发, 因此触发第二次`useEffect`:
所以第一个问题是, 不知道这样理解造成无限循环对不对?
### 第二个问题:
如果将请求数据部分抽成一个函数, 如下;
```
const CounterHook = props => {
  const [count, setCount] = useState(0)
  const [loading, setLoading] = useState(false)

  useEffect(() => {
    fetchApi()
  }, [fetchApi])

  const fetchApi = () => {
    setLoading(true)
    // 模拟发送数据
    setTimeout(() => {
      setLoading(false)
      setCount(1)
    }, 2000)
  }

  return ...
}
```
`useEffect`的依赖数组变成了一个函数, 而且此时似乎仍旧会造成无限循环. 同时有提示:
所以第二个问题为: 如果`useEffect`的依赖数组存在函数, 该如何理解这个函数是否"变化"? 例如上面例子里面, 为什么会造成无限循环, 函数到底是哪里"变化"了导致`useEffect`不断的被重新调用?
### 第三个问题
和第二个问题有关联, 按照提示修改, 使用`useCallback`包装了一下`fetchApi`这个函数,  代码如下:
```
const CounterHook = props => {
  const [count, setCount] = useState(0)
  const [loading, setLoading] = useState(false)

  useEffect(() => {
    fetchApiCallback()
  }, [fetchApiCallback])

  const fetchApiCallback = useCallback(() => {
    setLoading(true)
    // 模拟发送数据
    setTimeout(() => {
      setLoading(false)
      setCount(1)
    }, 2000)
  }, [])

  return ...
```
问题: `useCallback`依赖添加了一个依赖数组, 里面为空, 似乎代码没有出现无限循环的情况, 请问该如何解释? `useCallback`到底使得函数的"变化发生了怎样的改变"?
第一个问题：
对。
第二个问题：
函数组件的每次渲染都是执行一遍这个函数，在你的例子中，也就是 `CounterHook` 函数。那么两次执行中创建的局部函数，还会是同一个引用吗？不会的。所以本次执行中的 `fetchApi` 和上次执行中的 `fetchApi` 是两个不同的函数，因此 `useEffect` 的依赖被更新了，触发执行。
第三个问题：
`useCallback` 的返回值即为它接收的第一个参数，直到依赖更新。因此使用 `useCallback` 包裹的 `fetchApi` ，在依赖更新之前，总是同一个函数。也就不会触发 `useEffect`。