手写ReactHook题记录

83 阅读1分钟

什么是自定义钩子?

react.nodejs.cn/learn/reusi…

1、自定义钩子的意图是:在组件之间共享逻辑,它可以体现你的意图,但是封装了具体的实现。

2、自定义钩子的特点:

必须以 use 开头,后跟大写字母,例如 useStateuseOnlineStatus钩子可以返回任意值。

其次,里面应当使用其他hook,否则它没有必要成为一个自定义钩子,可以直接写一个普通的函数。 这不是强制的,但是因为hook只能在顶层调用,所以明确的通过名字来表示它是或不是一个钩子是有帮助的。

每次你的组件重新渲染时,所有钩子都会重新运行。

1. 手写useLocalStorage

大概意思就是实现一个可以更新,同时又存入localStorage的hook

// 实现
const useLocalStorage = (key, initialVal) => {
  // 初始值
  const prev = JSON.parse(localStorage.getItem(key));
  const [item, setItem] = useState(prev || initialVal);
  
  // item值改变时存入localStorage
  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(item));
  }, [item]);
  
  return [item, setItem];
};

// 使用方式
function App() {
  const [name, setName] = useLocalStorage('name', 'Bob');

  return (
    <input
      type="text"
      value={name}
      onChange={e => setName(e.target.value)}
    />
  );
}

2. 手写useBodyScrollLock

实现一个useBodyScrollLock ,当出现弹窗时 阻止背景滚动

方案一:适用于全平台,通过设置背景fixed

  const useBodyScrollLock = () => {
    let bodyEl = document.body;
    const top = useRef(0); // 注意这里要用ref
    // https://www.cnblogs.com/ypppt/p/13029915.html 参考方案三全平台
    function stopBodyScroll(shouldLock) {
      if (shouldLock) {
        top.current = window.scrollY;
        bodyEl.style.position = 'fixed';
        bodyEl.style.top = -top + 'px';
      } else {
        bodyEl.style.position = '';
        bodyEl.style.top = '';
        window.scrollTo(0, top.current); // 回到原先的top
      }
    }
    const disableScroll = () => stopBodyScroll(true);
    const enableScroll = () => stopBodyScroll(false);
    return [disableScroll, enableScroll];
  };
  const [disableScroll, enableScroll] = useBodyScrollLock();

方案二:适用于pc,移动端兼容不佳

    const useBodyScrollLock = () => {
    const docEl = document.body;
    const originalStyle = window.getComputedStyle(docEl).overflow;
    useLayoutEffect(() => {
      docEl.style.overflow = 'hidden';
      return () => {
        docEl.style.overflow = originalStyle;
      };
    }, []);
  };Ï