public (ログイン不要)なページと、 protected (要ログイン) なページの表示・非表示の状態をクライアント側で扱うロジックを共通化してしまうと、体験されたように状態管理が困難になります。
「ログイン不要なページだけど、一瞬だけ何も表示されない瞬間がある」「(ご指摘のように)ページ遷移が走る瞬間にページが表示されてしまう」といったことが起こりがちです。 (一応、 useEffect を使わずコンポーネントの中に直にリダイレクト処理を書く方法もありますが、ちょっと怖いです...)
Next.js App Router の機能である Route Groups を使うと、 public / protected なページを宣言的な方法で管理できます。 (わざわざ includes で判定する必要が無くなる)
それに、条件判定のネストが浅くなって、煩雑な状態管理が不要になりますし、 React のコンポーネントの仕組みによくフィットしていると思います。
app/
├─ (public)/ ... ログイン不要なページを固める
│ ├─ login/
│ │ └─ page.tsx
│ └─ signup/
│ └─ page.tsx
│
└─ (protected)/ ... ログインが必要なページを固める
├─ about/
│ └─ page.tsx
├─ privacy-policy/
│ └─ page.tsx
└─ layout.tsx ... 未ログイン時に login ページに飛ばす処理をここに書く