跳至主要內容

自定义 Hook

Mr.Chen《React》笔记Hook大约 3 分钟约 782 字

05. 自定义 Hook

通过自定义 Hook,可以将组件逻辑提取到可重用的函数中。

目前为止,在 React 中有两种流行的方式来共享组件之间的状态逻辑: render propsopen in new window高阶组件open in new window,现在让我们来看看 Hook 是如何在让你不增加组件的情况下解决相同问题的。

提取自定义 Hook

自定义 Hook 是一个函数,其名称以 “use” 开头,函数内部可以调用其他的 Hook。 例如,下面的 useFriendStatus 是我们第一个自定义的 Hook:

import { useState, useEffect } from 'react'

function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null)

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline)
    }

    ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange)
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange)
    }
  })

  return isOnline
}

与 React 组件不同的是,自定义 Hook 不需要具有特殊的标识。我们可以自由的决定它的参数是什么,以及它应该返回什么(如果需要的话)。换句话说,它就像一个正常的函数。但是它的名字应该始终以 use 开头,这样可以一眼看出其符合 Hook 的规则open in new window

使用自定义 Hook

现在我们已经把这个逻辑提取到 useFriendStatus 的自定义 Hook 中,然后就可以使用它了:

function FriendStatus(props) {
  const isOnline = useFriendStatus(props.friend.id)
  if (isOnline === null) {
    return 'Loading...'
  }
  return isOnline ? 'Online' : 'Offline'
}
function FriendListItem(props) {
  const isOnline = useFriendStatus(props.friend.id)
  return (
    <li style={{ color: isOnline ? 'green' : 'black' }}>{props.friend.name}</li>
  )
}

**这段代码等价于原来的示例代码吗?**等价,它的工作方式完全一样。如果你仔细观察,你会发现我们没有对其行为做任何的改变,我们只是将两个函数之间一些共同的代码提取到单独的函数中。自定义 Hook 是一种自然遵循 Hook 设计的约定,而并不是 React 的特性。

**自定义 Hook 必须以 “use” 开头吗?**必须如此。这个约定非常重要。不遵循的话,由于无法判断某个函数是否包含对其内部 Hook 的调用,React 将无法自动检查你的 Hook 是否违反了 Hook 的规则open in new window

**在两个组件中使用相同的 Hook 会共享 state 吗?**不会。自定义 Hook 是一种重用状态逻辑的机制(例如设置为订阅并存储当前值),所以每次使用自定义 Hook 时,其中的所有 state 和副作用都是完全隔离的。

**自定义 Hook 如何获取独立的 state?**每次调用 Hook,它都会获取独立的 state。由于我们直接调用了 useFriendStatus,从 React 的角度来看,我们的组件只是调用了 useStateuseEffect。 正如我们在之前章节open in new window了解到的open in new window一样,我们可以在一个组件中多次调用 useStateuseEffect,它们是完全独立的。

小总结

  1. 自定义 hook 就像一个普通函数,内部包含可复用的组件逻辑。
  2. 函数名以use开头。
  3. state是独立的。
上次编辑于: