繁体   English   中英

反应中的自定义钩子性能问题

[英]custom hook performance issues in react

我已将此 javascript 代码逻辑重写为要使用的反应自定义挂钩。

但似乎我所做的解决方案有点慢,而且性能很重,我想知道我可以通过哪种方式使其性能更高。

这是自定义钩子:

import { useEffect, useState } from 'react';
import { isBrowser } from '@utils/environment';
import { NAVBAR_HEIGHT_PX } from '@common/helpers';

export const useSticky = stickyElement => {
  const [offset, setOffset] = useState(NAVBAR_HEIGHT_PX);
  let offsetTop = NAVBAR_HEIGHT_PX;
  let currPos = isBrowser ? window.pageYOffset : 0;
  let endScroll = isBrowser ? window.innerHeight - stickyElement?.current?.offsetHeight - 500 : 0;

  useEffect(() => {
    if (!isBrowser) {
      return undefined;
    }

    const positionStickySidebar = () => {
      const { innerHeight, scrollY } = window;

      endScroll = innerHeight - stickyElement.current.offsetHeight;

      if (window.scrollY < currPos) {
        if (offsetTop < NAVBAR_HEIGHT_PX * 2) {
          offsetTop = offsetTop + currPos - scrollY;
        } else if (offsetTop >= NAVBAR_HEIGHT_PX * 2 && offsetTop !== endScroll) {
          offsetTop = NAVBAR_HEIGHT_PX * 2;
        }
      } else {
        if (offsetTop > endScroll) {
          offsetTop = offsetTop + currPos - scrollY;
        } else if (offsetTop < (endScroll) && offsetTop !== endScroll) {
          offsetTop = endScroll;
        }
      }
      setOffset(offsetTop);
      currPos = window.scrollY;
    };

    window.addEventListener('resize', positionStickySidebar, {
      capture: false,
      passive: true,
    });
    window.addEventListener('scroll', positionStickySidebar, {
      capture: false,
      passive: true,
    });

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

  return offset;
};

这是它的用法

const divRef = useRef(null);
const offsetTop = useSticky(divRef);

  <ContentContainer offsetTop={offsetTop} ref={divRef}>

这是样式化的组件:

export const ContentContainer = styled.div`
  position: sticky;
  top: ${({ offsetTop }) => `${offsetTop}px`};
`;

我建议两件事:

  1. 在 useCallback function 中移动所有变量(除了 useState)。 这种方式在每次渲染时不会重新计算这些值。 对于endScroll变量尤其重要,因为它在计算中使用offsetHeight 每次调用offsetHeight都会导致浏览器中的回流过程,这对性能影响很大。 因此,在每次渲染时调用它并不是一件好事,尤其是在这种计算不会影响任何事情的情况下(第一次渲染除外)。
  // Instead of this:
  export const useSticky = stickyElement => {
    // ...
    let offsetTop = NAVBAR_HEIGHT_PX;
    let currPos = isBrowser ? window.pageYOffset : 0;
    let endScroll = isBrowser ? window.innerHeight - stickyElement?.current?.offsetHeight - 500 : 0;
    // ...
  }


  // Do this:
  export const useSticky = stickyElement => {
    // ...
    useEffect(() => {
      if (!isBrowser) return undefined;
      let offsetTop = NAVBAR_HEIGHT_PX;
      let currPos = isBrowser ? window.pageYOffset : 0;
      let endScroll = isBrowser ? window.innerHeight - stickyElement?.current?.offsetHeight - 500 : 0;
      const positionStickySidebar = () => {
    // ...
  }
  1. 如果可能,摆脱偏移量 state ( const [offset, setOffset] =... )。 如果更换,性能应该会好得多
const [offset, setOffset] = useState(NAVBAR_HEIGHT_PX);
// ...
setOffset(offsetTop);
// ...
return offsetTop;

const topOffsetRef = useRef(NAVBAR_HEIGHT_PX);
// ...
stickyElement.current.style.top = offsetTop + 'px';
topOffsetRef.current = offsetTop;
// ...
return topOffsetRef.current;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM