dwook.record
Published on

Window 스크롤

Authors
  • avatar
    Name
    dwook
history.scrollRestoration

if (history.scrollRestoration) {
    // 스크롤 복원 비활성화
  window.history.scrollRestoration = 'manual';
}
  • auto
    • 페이지 내에서 사용자의 스크롤이 위치했던 곳으로 복원
  • manual
    • 스크롤 위치를 복원하지 않음
  • IE에서 history.scrollRestoration 아예 미지원
import {
    useEffect,
    useCallback,
} from 'react';

export default function useScrollRestoration() {
    const getHasState = useCallback(() => {
        const prevState = window.history.state || {};
        return prevState && prevState.state && prevState.state[`back_${window.location.href}`];
    }, []);

    const getParam = useCallback(
        keyName => window.history.state.state[`back_${window.location.href}`][keyName],
        [],
    );

    const storeScroll = useCallback((param) => {
        const key = `back_${window.location.href}`;
        const prevState = window.history.state || {};
        const parseParam = param || {};
        const nexState = {
            ...prevState,
            state: {
                ...prevState.state,
                [key]: {
                    ...parseParam,
                    scrollTop: window.pageYOffset,
                },
            },
            originalState: window.history.state,
        };
        window.history.replaceState(nexState, 'scrollData');
    }, []);

    const restoreScroll = useCallback((keyName, callback) => {
        const key = `back_${window.location.href}`;
        const prevState = window.history.state || {};
        if (getHasState()) {
            const newState = { ...prevState.state };
            const { scrollTop } = newState[key];

            if (keyName && typeof callback === 'function') callback(newState[key][keyName]);
            delete newState[key];

            const nextState = {
                ...prevState,
                state: newState,
            };

            if (prevState.originalState) {
                window.history.replaceState(nextState, 'scrollData');
            } else {
                window.history.replaceState(null, 'scrollData');
            }
            setTimeout(() => window.scrollTo(0, scrollTop), 0);
        }
    }, [getHasState]);

    useEffect(() => {
        if ('scrollRestoration' in window.history) window.history.scrollRestoration = 'manual';
    }, []);

    return {
        getHasState,
        getParam,
        storeScroll,
        restoreScroll,
    };
}

참조링크