Skip to content

Commit

Permalink
fix(FullscreenModal): fix hooks implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
ajkl2533 committed Dec 16, 2020
1 parent 59de993 commit e5623dd
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 76 deletions.
2 changes: 1 addition & 1 deletion src/components/FullscreenModal/Footer/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { FlexContainer } from '../../FlexContainer';
import { ScrollToTop } from '../ScrollToTop';
import { FullscreenModalProps } from '../FullscreenModal.types';
import ModalContext from '../Context/Context';
import { useStickyFooter } from './useStickyFooter';
import { useStickyFooter } from '../hooks/useStickyFooter';

const BaseStickyFooter = styled.footer`
position: fixed;
Expand Down
2 changes: 1 addition & 1 deletion src/components/FullscreenModal/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { SSCIconNames } from '../../Icon/Icon.enums';
import { H2, H3 } from '../../typography';
import ModalContext from '../Context/Context';
import { FullscreenModalProps } from '../FullscreenModal.types';
import { useStickyHeader } from './useStickyHeader';
import { useStickyHeader } from '../hooks/useStickyHeader';

const BaseStickyHeader = styled.header`
position: fixed;
Expand Down
43 changes: 0 additions & 43 deletions src/components/FullscreenModal/Header/useStickyHeader.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { useCallback, useEffect, useState } from 'react';
import debounce from 'lodash.debounce';

import { useStickyObserver } from './useStickyObserver';

export const useStickyFooter = (
modalRef: React.MutableRefObject<HTMLElement>,
modalFooterRef: React.MutableRefObject<HTMLElement>,
Expand All @@ -10,18 +12,26 @@ export const useStickyFooter = (
shouldShowScrollToTopButton,
setShouldShowScrollToTopButton,
] = useState(false);

const showScrollToTopButton = useCallback(() => {
if (modalRef.current === null) return;
const isScrollable =
modalRef.current.scrollHeight > modalRef.current.offsetHeight;
setShouldShowScrollToTopButton(isScrollable);
setIsFixed(false);
}, [modalRef, setShouldShowScrollToTopButton]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const resizeListener = debounce(showScrollToTopButton, 200);
useEffect(() => {
showScrollToTopButton();
window.addEventListener('resize', debounce(showScrollToTopButton, 200));
}, [modalRef, showScrollToTopButton]);
window.addEventListener('resize', resizeListener);

return () => {
window.removeEventListener('resize', resizeListener);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const isInView = useCallback(() => {
if (modalRef.current === null || modalFooterRef.current === null) return;
Expand All @@ -38,35 +48,10 @@ export const useStickyFooter = (
) {
setIsFixed(true);
}
}, [isFixed, setIsFixed, modalRef, modalFooterRef]);
const [observer] = useState(new MutationObserver(() => isInView()));

useEffect(() => {
if (
modalRef.current !== null &&
modalFooterRef.current !== null &&
shouldShowScrollToTopButton
) {
observer.observe(modalRef.current, {
childList: true,
subtree: true,
attributes: true,
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isFixed]);

isInView();
modalRef.current.addEventListener('scroll', debounce(isInView, 100));
window.addEventListener('resize', debounce(isInView, 200));
}
return () => {
observer.disconnect();
};
}, [
observer,
modalRef,
modalFooterRef,
shouldShowScrollToTopButton,
isInView,
]);
useStickyObserver(modalRef, modalFooterRef, isInView);

return {
isFixed,
Expand Down
29 changes: 29 additions & 0 deletions src/components/FullscreenModal/hooks/useStickyHeader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { useCallback, useState } from 'react';

import { useStickyObserver } from './useStickyObserver';

export const useStickyHeader = (
modalRef: React.MutableRefObject<HTMLElement>,
modalHeaderRef: React.MutableRefObject<HTMLElement>,
): { isFixed: boolean } => {
const [isFixed, setIsFixed] = useState(false);

const isInView = useCallback(() => {
if (modalRef.current === null || modalHeaderRef.current === null) return;
const scrollOffset = modalRef.current.scrollTop;
const headerHeight = modalHeaderRef.current.scrollHeight;

if (isFixed && scrollOffset <= headerHeight) {
setIsFixed(false);
} else if (!isFixed && scrollOffset > headerHeight) {
setIsFixed(true);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isFixed]);

useStickyObserver(modalRef, modalHeaderRef, isInView);

return {
isFixed,
};
};
47 changes: 47 additions & 0 deletions src/components/FullscreenModal/hooks/useStickyObserver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useEffect, useRef } from 'react';
import debounce from 'lodash.debounce';

export const useStickyObserver = (
modalRef: React.MutableRefObject<HTMLElement>,
elementRef: React.MutableRefObject<HTMLElement>,
isInView: () => void,
): void => {
const observerRef = useRef(null);
const initialRender = useRef(true);
const scrollListener = debounce(isInView, 100);
const resizeListener = debounce(isInView, 200);

useEffect(() => {
let currentModalRef;

if (observerRef.current !== null) {
observerRef.current.disconnect();
}
observerRef.current = new MutationObserver(() => isInView());

if (modalRef.current !== null && elementRef.current !== null) {
currentModalRef = modalRef.current;
observerRef.current.observe(currentModalRef, {
childList: true,
subtree: true,
attributes: true,
});
isInView();

if (!initialRender) {
currentModalRef.removeEventListener('scroll', scrollListener);
window.removeEventListener('resize', resizeListener);
}
initialRender.current = false;

currentModalRef.addEventListener('scroll', scrollListener);
window.addEventListener('resize', resizeListener);
}
return () => {
observerRef.current.disconnect();
currentModalRef.removeEventListener('scroll', scrollListener);
window.removeEventListener('resize', resizeListener);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isInView]);
};

0 comments on commit e5623dd

Please sign in to comment.