MENU

[ React ref ]ダイアログを開いた時に自動スクロールさせたい

こんにちは!
現在Reactでフロントエンドの開発を担当している土井です😎!
今回はDOM参照に使うref属性の使い方について、実際の業務で詰まった事と解決方法をご紹介したいと思います!

目次

実現したいこと

ページからボタンを押下してダイアログを開く際に、下の画面イメージのように、ある一定の位置まで自動スクロールして表示したい。

ハマったこと

スクロール処理は、Element.ScrollTo() で対応できるが、肝心のElementの参照はどうするか?
当初はuseRefを使って参照しようとした。(以下のような感じで↓)

//ダイアログのrefオブジェクト
const dialogRef = useRef(null)

// ダイアログを開けたら、スクロールするuseEffect
React.useEffect(() => {
  if (open) {
    if (dialogRef.current !== null) {
      dialogRef.current.scrollTo(0, 2000); // スクロール処理
    }
  }
}, [open]); // 依存配列にはダイアログの開閉state

~~~~~~~~~~~~~~省略~~~~~~~~~~~~~~~~
      <Dialog
        open={open}   //  ダイアログの開閉state
        onClose={handleClose}
        scroll="paper"
        aria-labelledby="scroll-dialog-title"
        aria-describedby="scroll-dialog-description"
      >
        <DialogTitle id="scroll-dialog-title">Subscribe</DialogTitle>
        <DialogContent
          dividers
          ref={dialogRef}    //  ref属性にrefオブジェクトをセット
        >

しかし、ダイアログを開いた時は、dialogRef.current が nullになっておりスクロール処理が実行すころとが出来ない。
なぜdialogRef.currentがnullになっているのか?

原因

Dialogは常にDOM内には存在せず、Dialogを開いた際にマウントされるため。
openがtrueになった時点ではまだマウントされておらず、dialogRef.currentはnullになるらしい。

<補足>
マウント   : DOMnodeがDOMツリーに追加されること
ちなみに混同しやすいものとして”レンダリング”もありますが、レンダリングはreactコンポーネントからDOMnodeを作るためにpropsとかstateなどが読み込まれる処理です。

解決方法

refオブジェクトはstateのように中身に変更があった際の通知はされないので、useEffectは使えない。
React公式にも記載があるが、ref属性にコールバック関数を渡して、そのコールバック関数の中でスクロール処理を実行することができる!
またコールバック関数の引数には、nodeを受け取ることが可能!!(←ここがポイント)
関数はref属性に更新がある(マウントする)度に呼び出されるので、
つまり、マウントされてnodeが参照できるようになった段階で何らかの処理が可能になる。
コールバック関数は、以下のように実装。

cost scrollDialog = useCallback((node) => { // 引数にnodeを受け取る
    if (!node) return;  // nodeがnullの場合はリターンして処理終了
    if (node.scrollTop !== 2000) {
        node.scrollTo(0, 2000); // スクロール処理
    }
},[]);

~~~~~~~~~~~~~~省略~~~~~~~~~~~~~~~~
      <Dialog
        open={open}   //  ダイアログの開閉state
        onClose={handleClose}
        scroll="paper"
        aria-labelledby="scroll-dialog-title"
        aria-describedby="scroll-dialog-description"
      >
        <DialogTitle id="scroll-dialog-title">Subscribe</DialogTitle>
        <DialogContent
          dividers
          ref={scrollDialog}    //  ref属性にコールバック関数をセット
        >

React公式はこちら

最初は、なぜrefオブジェクトがnullになるのか原因が掴めず、解決に結構時間を要してしまった。
なんだかんだ公式を読むのはやはり大事と実感しました😄

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

miracleaveはワクワクする最高のITサービスをユーザーに提供するテクノロジー集団です。
「ITでワクワクできる未来へ」をミッションに掲げ、楽しいを創り出す組織から、お客様に感動を与えるようなサービスを届けること、そして、新たな挑戦をする人をデジタルコンテンツの力で後押し、幸せな未来を作っていきたいと考えています。

目次