hooks学习笔记—hooks的典型案例

清除 effect

通常,组件卸载时需要清除 effect 创建的诸如订阅或计时器 ID 等资源。要实现这一点,useEffect 函数需返回一个清除函数。也就是说,要想在组件销毁的时候搞一些事情,需要useEffect 末尾返回一个函数,在这个函数里面可以写具体销毁的内容。

看下面的例子,在当前页面里面,页面的标题是'测试title',当切换到其他页面时,页面的标题变成‘前端精读’

import React, { useEffect } from 'react';

function useDocumentTitle(title) {
  useEffect(() => {
    document.title = title;
    return () => {
      console.log('销毁1————————————————');
      document.title = '前端精读';
    };
  }, [title]);
}

export default function CheckboxDemo() {
  useDocumentTitle('测试title');

  return 
; }

监听页面大小变化,网络是否断开

效果:在组件调用 useWindowSize 时,可以拿到页面大小,并且在浏览器缩放时自动触发组件更新。

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

function getSize() {
  return {
    innerHeight: window.innerHeight,
    innerWidth: window.innerWidth,
    outerHeight: window.outerHeight,
    outerWidth: window.outerWidth,
  };
}

function useWindowSize() {
  const [windowSize, setWindowSize] = useState(getSize());

  function handleResize() {
    setWindowSize(getSize());
  }

  useEffect(() => {
    window.addEventListener('resize', handleResize);

    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []);
  return windowSize;
}

export default function Demo() {
  const windowSize = useWindowSize();
  return 
页面宽度{windowSize.innerWidth}
; }

动态注入 css

效果:在页面注入一段 class,并且当组件销毁时,移除这个 class。

const className = useCss({
  color: "red"
});

return 
Text.
;

实现:可以看到,Hooks 方便的地方是在组件销毁时移除副作用,所以我们可以安心的利用 Hooks 做一些副作用。注入 css 自然不必说了,而销毁 css 只要找到注入的那段引用进行销毁即可,具体可以看这个 代码片段。

DOM 副作用修改 / 监听场景有一些现成的库了,从名字上就能看出来用法: document-visibility、 network-status、 online-status、 window-scroll-position、 window-size、 document-title。

组件辅助

Hooks 还可以增强组件能力,比如拿到并监听组件运行时宽高等。

获取组件宽高

效果:通过调用 useComponentSize 拿到某个组件 ref 实例的宽高,并且在宽高变化时,rerender 并拿到最新的宽高。

import React, { useLayoutEffect, useState, useRef } from 'react';

function getSize(el) {
  if (!el) {
    return {};
  }

  return {
    width: el.offsetWidth,
    height: el.offsetHeight,
  };
}

function useComponentSize(ref) {
  const [ComponentSize, setComponentSize] = useState(getSize(ref.current));

  function handleResize() {
    if (ref && ref.current) {
      setComponentSize(getSize(ref.current));
    }
  }

  useLayoutEffect(() => {
    handleResize();

    let resizeObserver = new ResizeObserver(() => handleResize());
    resizeObserver.observe(ref.current);

    return () => {
      resizeObserver.disconnect(ref.current);
      resizeObserver = null;
    };
  }, []);
  return ComponentSize;
}

export default function Demo() {
  const ref = useRef(null);
  const componentSize = useComponentSize(ref);
  return (
    <>
      {componentSize.width}