簡體   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