学习React 的第十六天 自定义Hook

139 阅读2分钟

“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 16 天,点击查看活动详情

1. 简介

在之前的学习中我们一直都是以函数式组件来开发的,函数式组件又是以Hook使用 state 以及其他的 React 特性,我们之前学习了挺多内置Hook的,但是在实际开发中我们可能会遇到这样的场景,将组件逻辑提取到可重用的函数中来自定义 Hook

2. 代码案例

在两个函数之间重复复用逻辑时,我们会把它提取到第三个函数中。而组件和 Hook 都是函数,所以也同样适用这种方式,自定义 Hook 是一个函数,其名称以 “use” 开头,函数内部可以调用其他的 Hook

1. 自定义一个滚动距离顶部的hook

  1. 通过监听scroll方法来获取document.documentElement.scrollTop值,赋予状态Y值,并返回
import {useState} from "react";

export function useWindowScroll() {
    const [y, setY] = useState(0)
    window.addEventListener('scroll', () => {
        const h = document.documentElement.scrollTop
        setY(h)
    })

    return [y]
}
  1. 使用自定义hook

通过直接导入hook使用,并且打印Y就可以看到hook被触发了

import {useWindowScroll} from "../hooks/useWindowScroll";

export default function demo02() {

    // 使用自定义hook
    const [y] = useWindowScroll()

    return (
        <>
            <div className="box">
                <div className="box-center">{y}</div>
            </div>
        </>
    )
}

2. 自定义hook,监听数据,自动存储同步到localStorage

  1. 在该hook中我们看到,可以在自定义中使用我们的内置Hook
import {useEffect, useState} from "react";

/**
 * 只要message 变化, 就自动同步到本地
 */
export function useLocalStorage(key: string, defaultValue: string) {
    const [message, setMessage] = useState(defaultValue)
    useEffect(() => {
        window.localStorage.setItem(key, message)
    }, [message, key])

    return [message, setMessage]
}
  1. 使用Hook

因为自定义的HookuseLocalStorage 是返回了一个数组数据,我们接受也是以以数组形式来接受,并且使用方法与内置Hook useState一样,通过调用setMessage之后触发了自定义Hook之中的useEffect把数据存储到localStorage

import {useLocalStorage} from "../hooks/useLocalStorage";

export default function demo02() {

    // 使用自定义hook
    const [message, setMessage] = useLocalStorage('name', "")

    return (
        <>
            <div className="box">
                {message}
                <button onClick={() => setMessage('张飞')}>修改message</button>
            </div>
        </>
    )
}

3. 总结

  1. 自定义 Hook 是一个函数,其名称以 “use” 开头,函数内部可以调用其他的 Hook
  2. 自定义 Hook 必须以 “use” 开头 必须如此。这个约定非常重要。不遵循的话,由于无法判断某个函数是否包含对其内部 Hook 的调用,React 将无法自动检查你的 Hook 是否违反了 Hook 的规则
  3. 在两个组件中使用相同的 Hook 不会共享 state ,自定义 Hook 是一种重用状态逻辑的机制(例如设置为订阅并存储当前值),所以每次使用自定义 Hook 时,其中的所有 state 和副作用都是完全隔离的。