🏓

React でボタンを押すとTOPに戻るスクロール機能

2021/06/18に公開1

いわゆる「TOPへ戻るボタン」ですが、jQueryだと検索すれば秒でヒットするんですが、「あれ?Reactだとどうやるんだ?」となったので共有しておきます。
ライブラリを使ったパターンと、使わないパターンでいい感じに書いてくれている方がお二方いらっしゃったので、その参考記事を元に2パターン共有します。

完成イメージ

サービスロゴを押すとTOPへ戻る機能
(このGIFはライブラリ使ったパターンです)
Image from Gyazo

前提条件

  • MacBook Air (M1, 2020)を使ってます。
  • create-react-app で作ったアプリに導入してます。
  • ファイル構成は主にトラハックさんの動画を参考にしてます。

ライブラリを使わないパターン

1.実際のコード

src/compornents/header/HeaderMenu.jsx
import React, { useState } from "react";
import HeaderLogo from "../../assets/img/src/timebooth_typo--s.png";
import SearchIcon from "@material-ui/icons/Search";
import ScheduleIcon from "@material-ui/icons/Schedule";
import { DrawerMenu } from ".";
import { AleartModal } from "../UIkit";
import "../../assets/css/header.css";

const returnTop = () => {
  window.scrollTo({
    top: 0,
    behavior: "smooth",
  });
};

const HeaderMenu = (props) => {
  const [openA, setOpenA] = useState(false);
  const [openB, setOpenB] = useState(false);

  const handleOpenA = () => {
    setOpenA(true);
  };
  const handleCloseA = () => {
    setOpenA(false);
  };
  const handleOpenB = () => {
    setOpenB(true);
  };
  const handleCloseB = () => {
    setOpenB(false);
  };

  return (
    <>
      <div className="header-container">
        <div className="header-container--inner">
          <div className="flex-row">
            <img className="logo-title hover1" src={HeaderLogo} alt="ロゴ画像" onClick={returnTop} />
            <div className="header-icon flex-row--justright hover1 header-icon-adjust ">
              <SearchIcon style={{ fontSize: 20 }} onClick={handleOpenA} />
              <AleartModal
                title="検索機能"
                text="準備中です"
                open={openA}
                handleClose={handleCloseA}
                onClick={handleCloseA}
              />
            </div>

            <div className="header-icon hover1 header-icon-adjust ">
              <ScheduleIcon style={{ fontSize: 20 }} onClick={handleOpenB} />
              <AleartModal
                title="スケジュール表示機能"
                text="準備中です"
                open={openB}
                handleClose={handleCloseB}
                onClick={handleCloseB}
              />
            </div>

            <div className="header-rightーadjust">
              <DrawerMenu fontSize={20} isLoginPage={props.isLoginPage} />
            </div>
          </div>
        </div>
      </div>
      <div className="header-container--foundation"></div>
    </>
  );
};

export default HeaderMenu;

ポイント

javascriptのwindow.scrollToメソッドを使った関数を作って、ボタン押して呼び出すだけです。
めっちゃシンプルでしたね。
これを検索せずに、さっと思い浮かべて実装できるように精進したいところです!

関数作って

const returnTop = () => {
  window.scrollTo({
    top: 0,
    behavior: "smooth",
  });
};

任意のボタン(onClick)で呼び出す

<img className="logo-title hover1" src={HeaderLogo} alt="ロゴ画像" onClick={returnTop} />

これで終了です。

ライブラリを使ったパターン

1.ライブラリのインストール

root
$ npm install react-scroll

2.実際のコード

src/compornents/header/HeaderMenu.jsx
import React, { useState } from "react";
import HeaderLogo from "../../assets/img/src/timebooth_typo--s.png";
import SearchIcon from "@material-ui/icons/Search";
import ScheduleIcon from "@material-ui/icons/Schedule";
import { animateScroll as scroll } from "react-scroll";
import { DrawerMenu } from ".";
import { AleartModal } from "../UIkit";
import "../../assets/css/header.css";

const scrollToTop = () => {
  scroll.scrollToTop();
};

const HeaderMenu = (props) => {
  const [openA, setOpenA] = useState(false);
  const [openB, setOpenB] = useState(false);

  const handleOpenA = () => {
    setOpenA(true);
  };
  const handleCloseA = () => {
    setOpenA(false);
  };
  const handleOpenB = () => {
    setOpenB(true);
  };
  const handleCloseB = () => {
    setOpenB(false);
  };

  return (
    <>
      <div className="header-container">
        <div className="header-container--inner">
          <div className="flex-row">
            <img className="logo-title hover1" src={HeaderLogo} alt="ロゴ画像" onClick={scrollToTop} />
            <div className="header-icon flex-row--justright hover1 header-icon-adjust ">
              <SearchIcon style={{ fontSize: 20 }} onClick={handleOpenA} />
              <AleartModal
                title="検索機能"
                text="準備中です"
                open={openA}
                handleClose={handleCloseA}
                onClick={handleCloseA}
              />
            </div>

            <div className="header-icon hover1 header-icon-adjust ">
              <ScheduleIcon style={{ fontSize: 20 }} onClick={handleOpenB} />
              <AleartModal
                title="スケジュール表示機能"
                text="準備中です"
                open={openB}
                handleClose={handleCloseB}
                onClick={handleCloseB}
              />
            </div>

            <div className="header-rightーadjust">
              <DrawerMenu fontSize={20} isLoginPage={props.isLoginPage} />
            </div>
          </div>
        </div>
      </div>
      <div className="header-container--foundation"></div>
    </>
  );
};

export default HeaderMenu;

ポイント

ライブラリをしないパターンとほとんど同じですが、importをしないと使えないので注意です。

import { animateScroll as scroll } from "react-scroll";

関数作って

const scrollToTop = () => {
  scroll.scrollToTop();
};

任意のボタン(onClick)で呼び出す

<img className="logo-title hover1" src={HeaderLogo} alt="ロゴ画像" onClick={scrollToTop} />

これで終了です!

参考

https://www.npmjs.com/package/react-scroll
https://qiita.com/TK-C/items/57f8e2283b46655b98f0
https://qiita.com/takk0715/items/6b82d7b4d13134d717eb
Reactアプリ全般で参考にしているトラハックさん
YouTubeのvideoIDが不正ですhttps://www.youtube.com/channel/UC-bOAxx-YOsviSmqh8COR0w

追伸

簡単に実装するならライブラリを使わないパターンの方が、ライブラリの更新を気にしなくて良いですし、安心で簡単ですね。
でもreact-schrollライブラリはLink機能を使えばコンポーネント別に飛べる便利な機能もあります。
LPとかポートフォリオサイトにはピッタリの機能かと思います。
参考リンクの記事の方が丁寧に書いてくださっているので、当てはまる方はぜひお試しを。

Discussion

nap5nap5

Footer側にボタン配置した場合のデモにチャレンジしてみました