Home
Next.js
react-scrollでページ内スクロールが効かない時と複数ページの対応

react-scrollでページ内スクロールが効かない時と複数ページの対応

公開日
2023.07.22
更新日
2023.07.23
react-scrollでページ内スクロールが効かない時と複数ページの対応

どうも!かけちまるです!

Reactで一瞬にしてページ内リンクでスムーススクロールを実装できるreact-scroll
しかし、react-scrollの実装はできているはずなのにスムーススクロールが機能しない。
例えば、共通ヘッダーでトップページではページ内リンク先はあるけど、下層ページにはページ内リンク先がない時はどうしようというあたりを解説します。

この記事では、

  • ・react-scrollの使い方
  • ・react-scrollが効かない時の対処法
  • ・共通ヘッダーの対処法

がわかります。

react-scrollの使い方

Next.jsで使用することを想定して説明したいと思います。
Reactでもほぼ設定方法は同じです👍
コンポーネントが別々でもしっかり動きます。

実装手順は次のような感じです。

  • ①react-scrollをインストール
  • ②遷移先要素にid属性をつける
  • ③react-scrollの設定を行う
1

react-scrollをインストール

npmyarnでreact-scrollをインストールします。

ターミナル
開く&閉じるコピー
// npmの場合 npm install react-scroll // yarnの場合 yarn add react-scroll
2

遷移先要素にid属性をつける

次は、遷移先要素にid属性をつけます。
名前は任意の値でOK!

Next.js
開く&閉じるコピー
<section id="contact"> ・・・ </section>
3

react-scrollの設定を行う

Next.js
開く&閉じるコピー
import { Link as Scroll } from 'react-scroll' export default function Header() { return ( <> <header>      ・・・ <Scroll to='contact' smooth={ true } duration={ 600 } offset={ -100 }>お問い合わせ</Scroll>      ・・・ </header> </> ) }

まず、react-scrollからLinkコンポーネントをimportします。
LinkコンポーネントをScrollに変更しているのは、Next.jsではnext/linkLinkコンポーネントを使ってリンクを設定すると思うので名前が混在しないようにしています。

Scrollコンポーネントに設定するオプションの説明ですが、

オプション 説明
to 遷移先のターゲット(id属性)を設定
smooth trueにするとターゲットまでスクロールする
duration スムーススクロールの時間
offset ターゲット位置に追加して〇〇px移動

つまり、id=”contact”要素の-100pxまで600msでスクロールしながら移動するということです。

これで通常は実装できるかと思います。

react-scrollが効かない時の対処法

react-scrollの使い方の通り設定してもピクリともしない時の対処法の説明です。

CSSでhtml、bodyタグにheight: 100%;をあてている。

コンテンツをフルページ表示するためにCSSでhtmlbodymainタグにheight: 100%;をあてているとreact-scrollがうまく機能しないようです。
Next.jsだと#_nextもですかね。

気づきにくいですね。

共通ヘッダーの対処法

例えば、共通ヘッダーのように全てのページに読み込む場合、ページ内リンク先があったりなかったりします。
そこで、ページ内リンク先がある時はスムーススクロール
ない時はターゲット要素へページ遷移するようにしたいとします。
そんな時の対処法です。

以下のコードは、
トップページならスムーススクロールし、それ以外のページならターゲット要素へページ遷移する例です。

Next.js
開く&閉じるコピー
import { useRouter } from 'next/router' import Link from 'next/link' import { Link as Scroll } from 'react-scroll' export default function Header() { const router = useRouter(); return ( <> <header>      ・・・ (router.pathname == '/') ? // if文でメニューを出し分ける <> <Scroll to='contact' smooth={ true } duration={ 600 } offset={ -100 }>お問い合わせ</Scroll> </> : <> <Link href={`/#contact`} legacyBehavior> <a className={header.nav}>お問い合わせ</a> </Link> </> }      ・・・ </header> </> ) }

next/routeruseRouterpathnameで現在ページのpathを取得してif文でメニューの出し分けをしています。

Reactの場合は、どうにかしてpathを取得するとかページを識別できればいいと思います。

Next.js 13.4でApp Router使用している場合

ここからは、react-scrollは関係なく、useRouterについてです。
もし、以下のようなエラーが出ていたら、Next.js13.4でApp Routerを採用している人かもしれません。

エラー
  • NextRouter was not mounted

これは、App Routerを採用しているとuseRouterの呼び出し元が違うようです。
pathを取得する際は、以下のようにすると良いと思います。

Next.js
開く&閉じるコピー
import { usePathname } from 'next/navigation' import Link from 'next/link' import { Link as Scroll } from 'react-scroll' export default function Header() { const pathname = usePathname(); return ( <> <header>      ・・・ (pathname == '/') ? // if文でメニューを出し分ける <> <Scroll to='contact' smooth={ true } duration={ 600 } offset={ -100 }>お問い合わせ</Scroll> </> : <> <Link href={`/#contact`} legacyBehavior> <a className={header.nav}>お問い合わせ</a> </Link> </> }      ・・・ </header> </> ) }

参考にした記事

react-scroll react-scroll を導入し超簡単に画面内のスクロールを実装しよう | fwywd(フュード)powered by キカガク `NextRouter` was not mounted

おわり

かけちまる
かけちまる
Webエンジニアをしています。
HTML/CSS/JavaScript/jQuery/PHPができます。
WEB制作を中心に日々学びになったこと、興味が沸いたことについて初心者の方でもわかりやすいようにアウトプットしていくブログです。

関連記事

記事の目次にカレント表示機能を導入する😤

記事の目次にカレント表示機能を導入する😤

【jQuery】順番に要素が出てくるアニメーション

【jQuery】順番に要素が出てくるアニメーション

CSSだけでぷよぷよしたアニメーションの実装方法

CSSだけでぷよぷよしたアニメーションの実装方法

【基本編】JavaScriptのマウスイベントでドラッグ&ドロップ機能を実装する

【基本編】JavaScriptのマウスイベントでドラッグ&ドロップ機能を実装する

【CSSのみ】背景のグラデーションを変化させるアニメーション

【CSSのみ】背景のグラデーションを変化させるアニメーション

【GSAP入門】使い方となにができるのか

【GSAP入門】使い方となにができるのか