美文网首页
react hook -- 自定义Hook

react hook -- 自定义Hook

作者: 廖雪青 | 来源:发表于2022-12-29 20:28 被阅读0次

当我们想在两个函数之间共享逻辑时,我们会把它提取到第三个函数中。而组件和Hook都是函数,所以也同样适用这种方式。

认识自定义Hook

自定义Hook是一个函数,其名称以use开头,函数内部可以调用其他Hook。

在自定义Hook的顶层可以无条件地调用其他Hook(useState, useEffect)。
我们可以自由决定自定义Hook的参数返回值
自定义Hook必须以use开头,这样方便判断该函数内部是否调用了内部Hook,以及React能自动检查Hook是否违反了Hook的规则(见Hook规则部分)。
每次使用自定义Hook时,其中的state和副作用都是完全隔离的。

Hooks 和普通函数在语义上是有区别的,就在于函数中有没有用到其它 Hooks。

就是说如果你创建了一个 useXXX 的函数,但是内部并没有用任何其它 Hooks,那么这个函数就不是一个 Hook,而只是一个普通的函数。但是如果用了其它 Hooks ,那么它就是一个 Hook。

自定义Hook的特点

  • 名字一定是以 use 开头的函数,这样 React 才能够知道这个函数是一个 Hook。
  • 函数内部一定调用了其它的 Hooks,可以是内置的 Hooks,也可以是其它自定义 Hooks。这样才能够让组件刷新,或者去产生副作用。

可重用逻辑直接写一个工具类不就行了吗?为什么一定要通过Hook进行封装呢?

因为在 Hooks 中,你可以管理当前组件的 state,从而将更多的逻辑写在可重用的 Hooks 中。但是要知道,在普通的工具类中是无法直接修改组件 state 的,那么也就无法在数据改变的时候触发组件的重新渲染。

拆分逻辑的目的不一定是为了重用,而可以是仅仅为了业务逻辑的隔离。

在这个场景下,我们不一定要把 Hooks 放到独立的文件中,而是可以和函数组件写在一个文件中。这么做的原因就在于,这些 Hooks 是和当前函数组件紧密相关的,所以写到一起,反而更容易阅读和理解。

例:

function MyComponent() {
  const [id, setId] = useState(1);
  const isOnline = useOnlineStatus(id);

  return (
    <>
    // other nodes
    </>
  )
}

useState为我们提供了id的最新值,并把它做为参数传入useOnlineStatus, 当id改变时,useOnlineStatus Hook会取消订阅前一个id,并订阅新的id

例一:自定义 Hook 处理 LocalStorage 的存取

需求:希望把一些数据存储到 localStorage 中 - 不使用自定义Hook

不使用自定义Hook

import React, { useState, useEffect } from 'react'

export default function CustomDataStoreHook() {
  const [name, setName] = useState(() => {
    return JSON.parse(window.localStorage.getItem("name"))
  });

  useEffect(() => {
    window.localStorage.setItem("name", JSON.stringify(name));
  }, [name])

  return (
    <div>
      <h2>CustomDataStoreHook: {name}</h2>
      <button onClick={e => setName("gercke")}>设置name</button>
    </div>
  )
}

定义自定义Hook - useLocalStorage

import React,{useState, useEffect} from 'react';
function useLocalStorage(key) {
  const [data, setData] = useState(() => {
    return JSON.parse(window.localStorage.getItem(key))
  });

  useEffect(() => {
    window.localStorage.setItem(key, JSON.stringify(data));
  }, [data]);

  return [data, setData];
}

export default useLocalStorage;

使用自定义Hook

import React, { useState, useEffect } from 'react';

import useLocalStorage from '../hooks/local-store-hook';

export default function CustomDataStoreHook() {
  const [name, setName] = useLocalStorage("name");

  return (
    <div>
      <h2>CustomDataStoreHook: {name}</h2>
      <button onClick={e => setName("kobe")}>设置name</button>
    </div>
  )
}

例二:自定义Hook监听浏览器状态变化

需求:当 y > 300 时,显示Back to top按钮

定义自定义Hook - useScroll

import { useState, useEffect } from 'react';

// 获取横向,纵向滚动条位置
const getPosition = () => {
  return {
    x: document.body.scrollLeft,
    y: document.body.scrollTop,
  };
};
const useScroll = () => {
  // 定一个 position 这个 state 保存滚动条位置
  const [position, setPosition] = useState(getPosition());
  useEffect(() => {
    const handler = () => {
      setPosition(getPosition(document));
    };
    // 监听 scroll 事件,更新滚动条位置
    document.addEventListener("scroll", handler);
    return () => {
      // 组件销毁时,取消事件监听
      document.removeEventListener("scroll", handler);
    };
  }, []);
  return position;
};

使用自定义Hook

import React, { useCallback } from 'react';
import useScroll from './useScroll';

function ScrollTop() {
  const { y } = useScroll();

  const goTop = useCallback(() => {
    document.body.scrollTop = 0;
  }, []);

  const style = {
    position: "fixed",
    right: "10px",
    bottom: "10px",
  };
  // 当滚动条位置纵向超过 300 时,显示返回顶部按钮
  if (y > 300) {
    return (
      <button onClick={goTop} style={style}>
        Back to Top
      </button>
    );
  }
  // 否则不 render 任何 UI
  return null;
}

Hook 规则

  • 只在最顶层使用Hook
    • 不要在循环、条件或嵌套中调用Hook
  • 只在React函数中调用Hook
    • 在react的函数组件中调用Hook
    • 在自定义Hook中调用其他Hook

要确保Hook的调用顺序在每次渲染中都是相同的

相关文章

  • React hook 10种 Hook

    React hook 10种 Hook (详细介绍及使用) React Hook是什么?React官网是这么介绍的...

  • React Hook

    Through 4 questions introduce React Hook What is Hook? In...

  • react-hook-form使用

    官网地址:https://react-hook-form.com/[https://react-hook-form...

  • 学习react hook的总结

    react16推出了react hook,react hook使得functional组件拥有了class组件的一...

  • Vue3 Hooks 替代了 Vue2 Mixins

    前言 我们知道,React社区,已经全面拥抱Hook。Vue3的发布也支持了自定义Hook,作为只会Vue2的前端...

  • 自定义hook复用组件代码

    概念: 自定义hook是react中最新的组件代码复用方案注意点: hook必须以use开头,并需要使用别的hoo...

  • Hook

    hook 介绍 Hook 是 React16.8 的新特性。Hook 就是 JavaScript 函数, 它可以让...

  • react hook -- 自定义Hook

    当我们想在两个函数之间共享逻辑时,我们会把它提取到第三个函数中。而组件和Hook都是函数,所以也同样适用这种方式。...

  • react-hook

    react-hook

  • react hook介绍

    react hook是什么 react hook是react中引入新特性,它可以让react函数组件也拥有状态;通...

网友评论

      本文标题:react hook -- 自定义Hook

      本文链接:https://www.haomeiwen.com/subject/cdzaqdtx.html