LoginSignup
18
11

More than 1 year has passed since last update.

next/routerのisReadyフラグ

Last updated at Posted at 2021-08-03

isReadyとは

next.jsのRouterオブジェクトのisReady属性は、routerが完全に準備できているかどうかを表すフラグである。

isReady: boolean - Whether the router fields are updated client-side and ready for use. 
Should only be used inside of useEffect methods and not for conditionally rendering on the server.
  • ルータの各項目がクライアント側で更新されてから初めて使えるようになる
  • useEffect(やcomponentDidMount)でしか使わない。サーバ側レンダリングでそれの利用を避けるべき。

  • 参照の仕方

import { useRouter } from 'next/router';

export HogePage = () => {
  const router = useRouter();
  console.log('router:', router);
  console.log('router.isReady:', router.isReady);
  console.log('router.query?.a:', router.query?.a);
  return (
    <div>test</div>
 );
};

isReadyの値

ケースバイケースで状況によってisReadyの値が変わる。

SSRページの場合

isReadyの値は常にtrueである。

CSR/SSGページの場合

初期ロード クエリパラメータ isReady
YES あり false
YES なし true
NO あり true
NO なし true

つまり、物理遷移やブラウザリロードで、かつクエリパラメータがある場合だけ、一瞬isReadyがfalseになることがある。
その時、クエリパラメータの値がもらえない。

利用時の注意点

初期ロード時にisReadyがfalseであれば、router.query?.aのようにクエリパラメータの値がundefinedになってしまうので、画面レンダリングでそれを直接に使わない。
遅延処理を入れてisReadyがtrueになったら、それを再描画するようにしないといけない。

  • RouterReadyWaiterのようなHOCを作ったほうが良さそう
    • useEffectまたはcomponentDidUpdateでisReadyを監視して
      • falseなら、childrenを描画しない
      • trueの場合、childrenを描画する
    • childrenとしてReactコンポーネントではRouterが準備できている前提になるので、実装がラク。

なぜこうなるのか

一瞬next/routerのバグではないかと思ったが、よく考えたらそうではない。

  • SSRでない限り、事前にサーバ側で事前に用意されたプリレンダリングHTMLコンテンツをそのままクライアントに返す
    • つまり、クエリパラメータはプリレンダリングに影響しない
    • プリレンダリング結果がテンプレートと見なすなら、それを基づく更なる描画処理はクライアントでやる
    • hydration直後はrouterのクエリパラメータ無視の状態なので、isReadyがfalseになるしかない
  • SSRであれば、サーバ側でレンダリングするため、子いう問題はない

参考記事

18
11
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
18
11