📖

material-uiでスクロールしたら消えるAppBar

2021/06/26に公開

スクロールしたときの値を取得します。
スクロールが止まったときのタイミングを取得するのにsetTimeoutを使用しています。

export function useScroll()  {
    const [scrolling, setScrolling] = useState(false);
    const [scrollTop, setScrollTop] = useState(0);

    let handle:NodeJS.Timeout|null = null

    const listener = (e:any) => {
        if (handle) {
            clearTimeout(handle)
        }
        setScrolling(true)
        setScrollTop(e.target.documentElement.scrollTop)
        handle = setTimeout(() => {
            setScrolling(false)
        }, 500)
    };

    useEffect(() => {
        window.addEventListener("scroll", listener);
        return () => {
            window.removeEventListener("scroll", listener);
        };
    },[]);

    return { scrolling, scrollTop };
}

useScrollを用いてAppBarを制御します。

const useStyles = (theme: Theme) => {
    return makeStyles({
        root: {
            flexGrow: 1
        },
        flex: {
            flex:1
        },
        menuButton: {
            marginLeft: -12,
            marginRight:100
        },
        toolbarMargin:theme.mixins.toolbar
    })
}

const ScrollHideAppBar = () => {

    const theme = useTheme()
    const styles = useStyles(theme)()

    const { scrolling, scrollTop } = useScroll();
    
    return (
    <div>
        {
        !scrolling && (scrollTop == 0) &&
        <Fade in={!scrolling}>
        <AppBar position="fixed">
            <Toolbar>
                <IconButton className={styles.menuButton}
                    color="inherit"
                    aria-label="Menu">
                    <MenuIcon></MenuIcon>
                </IconButton>
                <Typography variant="h1" color="inherit" className={styles.flex}>
                    Title
                </Typography>
                <Button color="inherit">Login</Button>
            </Toolbar>
            </AppBar>
            </Fade>
            }
    </div>
    )
}

後は単純に使います。

const MyAppHide = () => {
    const theme = useTheme()
    const styles = useStyles(theme)()


    return (
        <div className={styles.root}>   
            <ScrollHideAppBar></ScrollHideAppBar>
            <div className={styles.toolbarMargin} />
            
            <ul >
                {new Array(500).fill(null).map((v, i) => (
                    <li key={i}>{i}</li>
                ))}
                </ul>
    </div>);
}

export default MyAppHide

Discussion