解決済
(Django REST Framework +Next.js)トップページにアクセスされた場合はログインしていなければログイン画面に強制遷移させたい。
Next.js
React
初心者
2023/07/05 12:00

実現したいこと

トップページ(localhost:3000)にアクセスされた場合にログインしていない時はログイン画面(localhost:3000/login)に遷移させたいのですが、Next.js側でどのように描けばよいかわかりません。

Router.push('/login')と書いてみましたが反応しません。
初歩的な質問で申し訳ございませんがどのようにすれば実現できるかご教示いただきたいです。

発生している問題

Next.js側で画面遷移できない。(書き方が間違っている?)

ソースコード

はるさんの「インスタ風画像投稿サイト構築」のpages/index.jsをアレンジしています。
Next.js側のpages/index.jsを下記のようにしました。

import Head from 'next/head'
import Image from 'next/image'
import styles from '../styles/Home.module.css'
import { reset_auth_status } from '../actions/auth'
import { useSelector,useDispatch } from 'react-redux'
import { useState, useEffect } from 'react'
import { useRouter } from 'next/router'

export default function Home() {

  const isAuthenticated = useSelector((state) => state.auth.isAuthenticated)
  const user = useSelector((state) => state.auth.user)

  const dispatch = useDispatch()
  const router = useRouter()

  // 状態解除
  useEffect(() => {
    if (dispatch && dispatch !== null && dispatch !== undefined) {
      dispatch(reset_auth_status())
      dispatch(reset_post_status())
    }
  }, [dispatch])


  return (
    <>
        {isAuthenticated && user ? (
          <div>
            <div>ようこそ、{user.name}さん</div>
            <div className="my-4 border-4 border-dashed border-gray-200 rounded">
              <div className="flex justify-center items-center h-64">こちらは無料コンテンツ!</div>
            </div>
          </div>
        ) : (
          () => router.push('/login')
        )}
    </>
  )
}

自分で試したこと

Next.js側でrouter.pushをつかってみました。
エラーは出ませんが画面遷移もしません。

回答 3件
login
回答するにはログインが必要です

useEffectを使用するときは、必ず、[]が必要になります。

useEffect(()=>{
    if (isAuthenticated === false){
      router.push("/login");
    }
}, [isAuthenticated]) // ←追加

useRequireLogin関数のコールを一番上にもってきたらいかがでしょうか?

export default function Home() {
    useRequireLogin();

あと、reducersのisAuthenticatedの初期値はnullであることを確認しておいてください。

useEffect使用の際は最後の[]が必要という事、勉強になりました。
ありがとうございます。

useRequireLogin();を一番上に記述するように訂正しました。
これでURLを直接手で入力されても強制リダイレクトが実現できました。

一瞬だけ画面が表示されて格好悪い部分については、よくある「くるくる」アイコンを表示する部分を実装して見えないようにしようと思います。

1

はる先生。

下記のようにカスタムフック?を作りましたら強制遷移実現しました。

①プロジェクトディレクトリに「hooks/useRequireLogin.js」を新規作成。

②hooks/useRequireLogin.jsを下記のようにする。

import { useEffect } from 'react'
import { useRouter } from 'next/router';
import { useSelector } from 'react-redux';

export function useRequireLogin() {

  const isAuthenticated = useSelector((state) => state.auth.isAuthenticated)
  const router = useRouter();

  useEffect(()=>{
    if (isAuthenticated == false){
      router.push("/login"); // ←訂正
    }

  })

}

③画面遷移させたいページにカスタムフックをインポートし記述する
例)pages/index.js

import Head from 'next/head'
import Image from 'next/image'
import styles from '../styles/Home.module.css'
import { reset_auth_status } from '../actions/auth'
import { useSelector,useDispatch } from 'react-redux'
import { useState, useEffect } from 'react'
import { useRouter } from 'next/router'
import { useRequireLogin } from "../hooks/useRequireLogin" //※ ←カスタムフック追加

export default function Home() {

  const isAuthenticated = useSelector((state) => state.auth.isAuthenticated)
  const user = useSelector((state) => state.auth.user)

  const dispatch = useDispatch()
  const router = useRouter()

  // 状態解除
  useEffect(() => {
    if (dispatch && dispatch !== null && dispatch !== undefined) {
      dispatch(reset_auth_status())
      dispatch(reset_post_status())
    }
  }, [dispatch])

  useRequireLogin(); //※ ←カスタムフック追加


  return (
    <>
        {isAuthenticated && user ? (
          <div>
            <div>ようこそ、{user.name}さん</div>
            <div className="my-4 border-4 border-dashed border-gray-200 rounded">
              <div className="flex justify-center items-center h-64">こちらは無料コンテンツ!</div>
            </div>
          </div>
        ) : undefined}
    </>
  )
}



一応、これで画面遷移は出来ました。
ただ、一瞬そのページが表示されてしまい格好悪いです。
良い方法をご教示いただきたいです。

1