1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【React】スクロールバーのあるDrawerをスクロールして閉じた後、再表示時に先頭に戻っているようにしたい

Posted at

背景

クマの出没場所を全国規模で登録できるアプリを作成中の事象です。

下のgifのように、スクロールバーが表示されるDrawerメニューを実装したところ、下までスクロール → 登録ボタン押下 → 再表示時した後に、先頭に戻らせたい…という願望が生じました。

(登録したデータはテスト環境のもので、実際に起きたことではありません)
scroll is not good.gif

動作環境

  • node.js ver 18.18.2
  • next.js ver 14.0.3
  • react ver 18
  • mui/material ver 5.16.7

試したこと

  • Drawerの初期表示時に scrolTo でトップに戻させる
  • 閉じるボタン、登録ボタンを押したときに、 scrllTo でトップに戻させる

いずれも再表示時、トップに戻るようにはなりませんでした。同期処理で表示 → スクロール の順序を確定させれば可能かもしれませんが、そこまで難しく考えたくない…という願望もありました。

解決策

keyを用いたコンポーネントの再レンダリングを利用します。
参考:https://ja.react.dev/learn/preserving-and-resetting-state#resetting-a-form-with-a-key

type Props = {
    onRegisterClick: () => void;
    onClose: () => void;
};

export function PlaceDrawer(props: Props) {
    const drawerKey = useRef<number>(0);

    return (
        <>
            <Drawer key={drawerKey.current}>
                <Box>
                    <Grid container spacing={2} sx={{ marginTop: "24px" }}>
                        <Grid item xs={6}>
                            <Button
                                onClick={() => {
                                    props.onClose();
                                    // HACK: クリック時にスクロールをトップに戻すのが困難なため、コンポーネント自体の再レンダリングで対応
                                    drawerKey.current = drawerKey.current + 1;
                                }}
                            >
                                地図に戻る
                            </Button>
                        </Grid>
                        <Grid item xs={6} sx={{ textAlign: "right" }}>
                            <Button
                                onClick={async () => {
                                    props.onRegisterClick();
                                    // HACK: クリック時にスクロールをトップに戻すのが困難なため、コンポーネント自体の再レンダリングで対応
                                    drawerKey.current = drawerKey.current + 1;
                                }}
                            >
                                登録する
                            </Button>
                        </Grid>
                    </Grid>
                </Box>
            </Drawer>
        </>
    );
}

(登録したデータはテスト環境のものです)
scroll is so good.gif

keyが変更された際、コンポーネントは再レンダリングされる(違うものとして扱われる)ため、 PlaceDrawer が再表示された時には先頭に戻った状態になります。
再レンダリングがパフォーマンスに影響を与える可能性(要検証)もありますが、個人開発のレベルであれば上のような方法でも良いのかなと思います。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?