コード例 #1
0
export default (domRef, {
  initialScroll = null,
  inaccuracy = 0,
  runScroll = defaultRunScroll,
} = {}) => {
  const wasScrolled = useRef(null);

  const isScrolled = useCallback(
    () => Math.ceil(domRef.current.scrollTop) >= maxScrollTop(domRef.current) - inaccuracy,
    [inaccuracy],
  );

  useLayoutEffect(() => {
    const onScroll = () => { wasScrolled.current = isScrolled(); };

    domRef.current.addEventListener('scroll', onScroll);
    return () => domRef.current.removeEventListener('scroll', onScroll);
  }, []);

  const scroll = useCallback((position) => {
    invariant(domRef.current !== null, `Trying to scroll to the bottom, but no element was found.
      Did you call this scrollBottom before the component with this hook finished mounting?`);

    const offset = position === Infinity ? maxScrollTop(domRef.current) : position;
    runScroll(domRef.current, offset);
  }, [runScroll]);

  const scrollBottom = useCallback(() => {
    scroll(Infinity);
  }, [scroll]);

  const stayScrolled = useCallback(() => {
    if (wasScrolled.current) scrollBottom();

    return wasScrolled.current;
  }, [scrollBottom]);

  useLayoutEffect(() => {
    if (initialScroll !== null) {
      scroll(initialScroll);
    }

    wasScrolled.current = isScrolled();
  }, []);

  return {
    scroll,
    stayScrolled,
    scrollBottom,
    isScrolled,
  };
};
コード例 #2
0
function FocusOnMountMenuItem(props) {
  const listItemRef = React.useRef(null);
  React.useLayoutEffect(() => {
    listItemRef.current.focus();
  }, []);
  return <MenuItem {...props} ref={listItemRef} tabIndex={0} />;
}
コード例 #3
0
ファイル: About.js プロジェクト: kamenjan/portfolio
const About = ({ aboutData }) => {
  const aboutContainerRef = useRef(null)

  useLayoutEffect(() => {
    const aboutContainer = aboutContainerRef.current
    const viewportHeight = Math.max(
      document.documentElement.clientHeight,
      window.innerHeight || 0,
    )
    const aboutHeight = aboutContainer.clientHeight
    const offsetTop = aboutContainer.offsetTop
    const offsetBottom = viewportHeight - (offsetTop + aboutHeight)
    const validMargin = ((offsetTop + aboutHeight) / 100) * 20

    if (offsetBottom > 0 && offsetBottom < validMargin) {
      const newPadding = (offsetBottom - 40) / 2
      aboutContainer.style.padding = `${newPadding}px 0`
    }
  }, [])

  return (
    <Container ref={aboutContainerRef}>
      {aboutData.map((paragraph, i) => (
        <p key={i}>{paragraph}</p>
      ))}
    </Container>
  )
}
コード例 #4
0
function useBodyScrollLock() {
  useLayoutEffect(() => {
    const originalOverflow = window.getComputedStyle(document.body).overflow
    console.log('originalOverflow:', originalOverflow)
    document.body.style.overflow = 'hidden';

    // unlock the DOM on unmounting DishForm, destroy the effects
    return function cleanup() {
      document.body.style.overflow = originalOverflow;
    }
    // this ===> }, [])  to ensure function is only run on mount
  }, [])
}
コード例 #5
0
export function Nevergreen({initalise, loaded, isFullScreen, children, clickToShowMenu, fullScreenRequested, enableFullScreen, checkForNewVersion}) {
  const fullScreenTimer = useRef()

  const disableFullScreen = throttle(() => {
    clearTimeout(fullScreenTimer.current)

    if (isFullScreen) {
      enableFullScreen(false)
    }

    if (fullScreenRequested) {
      fullScreenTimer.current = setTimeout(() => enableFullScreen(true), THREE_SECONDS)
    }
  }, ONE_SECOND, {trailing: false})

  const checkVersion = useMemo(() => () => loaded && checkForNewVersion(version, window.location.hostname), [loaded])

  useEffect(() => {
    initalise()
  }, [])

  useLayoutEffect(() => {
    enableFullScreen(fullScreenRequested)
    if (!fullScreenRequested) {
      clearTimeout(fullScreenTimer.current)
    }
  }, [fullScreenRequested])

  useTimer(checkVersion, TWENTY_FOUR_HOURS)

  const disableFullScreenOn = clickToShowMenu
    ? {onClick: disableFullScreen}
    : {onMouseMove: disableFullScreen}

  return (
    <>
      {loaded && <KeyboardShortcuts/>}

      <div className={styles.nevergreen}
           aria-busy={!loaded}
           tabIndex='-1'
           {...disableFullScreenOn}>
        <Header fullScreen={isFullScreen}/>
        <NotificationContainer/>
        {loaded && <main className={styles.main}>{children}</main>}
        <Footer fullScreen={isFullScreen}/>
      </div>
    </>
  )
}