Closed3
Error: ( ) is not a function というエラーに遭遇
useLogin.tsx
"use client"
import useApi from "@/hooks/useApi"
import { useCallback, useEffect, useState } from "react"
interface UseLoginReturnType {
data: any
error: any
loading: boolean
email: string
password: string
setEmail: React.Dispatch<React.SetStateAction<string>>
setPassword: React.Dispatch<React.SetStateAction<string>>
fetchLoginData: () => void
handleLogin: (e: React.FormEvent<HTMLFormElement>) => void
}
const useLogin = (): UseLoginReturnType => {
const [email, setEmail] = useState<string>("")
const [password, setPassword] = useState<string>("")
const { data, error, loading, refetch } = useApi()
const fetchLoginData = useCallback(() => {
refetch("/auth/login", {
method: "POST",
data: { email, password }
})
}, [refetch])
const handleLogin = useCallback(async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
await fetchLoginData()
}, [fetchLoginData])
useEffect(() => {
if (data) {
console.log(data)
}
}, [data])
return {
data,
error,
loading,
fetchLoginData,
handleLogin,
email,
password,
setEmail,
setPassword
}
}
export default useLogin
auth/login/page.tsx
import React from 'react'
import Link from 'next/link'
import { InputField, Button } from '@/components'
import { FaSignInAlt } from 'react-icons/fa'
import { useLogin } from '@/features/auth'
const LoginPage = () => {
const {
data,
error,
loading,
email,
password,
setEmail,
setPassword,
handleLogin
} = useLogin()
return (
<div className="min-h-screen flex items-center justify-center bg-base02">
<div className="bg-white p-8 rounded-lg shadow-lg w-full max-w-md">
<h1 className="text-3xl font-bold text-main01 mb-6 text-center">ログイン</h1>
<form className="space-y-4" onSubmit={handleLogin}>
<InputField
type="email"
id="email"
placeholder="your@email.com"
label="メールアドレス"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<InputField
type="password"
id="password"
placeholder="••••••••"
label="パスワード"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<Button
type="submit"
text="ログイン"
icon={<FaSignInAlt className="inline-block mr-2" />}
loading={loading}
/>
</form>
<div className="mt-4 text-center">
<Link href="/auth/register" className="text-accent02 hover:underline">
アカウントをお持ちでない方はこちら
</Link>
</div>
</div>
</div>
)
}
export default LoginPage
auth/login/page.tsx
"use client"
を書いたら治った。
"use client"ディレクティブを追加することでエラーが解決。
- Next.jsのApp Routerでは、デフォルトでサーバーコンポーネントが使用されます。サーバーコンポーネントはサーバー側でレンダリングされ、クライアント側のJavaScriptを最小限に抑える。
- しかし、useLoginフックはクライアントサイドの機能(状態管理、イベントハンドリングなど)を使用しています。これらの機能はサーバー側では利用できない。
- "use client"ディレクティブを追加することで、Next.jsにこのコンポーネントとその子コンポーネントをクライアントサイドでレンダリングするよう指示。これにより、useLoginフックやその他のクライアントサイド機能が正常に動作するようになる。
- 特に、useLoginフックの実装を見ると、以下の部分でクライアントサイドの機能を使用している。
"use client"
import useApi from "@/hooks/useApi"
import { useCallback, useEffect, useState } from "react"
interface UseLoginReturnType {
data: any
error: any
loading: boolean
email: string
password: string
setEmail: (email: string) => void;
setPassword: (password: string) => void;
fetchLoginData: () => void
handleLogin: (e: React.FormEvent<HTMLFormElement>) => void
}
const useLogin = (): UseLoginReturnType => {
const [email, setEmail] = useState<string>("")
const [password, setPassword] = useState<string>("")
const { data, error, loading, refetch } = useApi()
- これらの機能(useState, useCallback, useEffect)はクライアントサイドでのみ動作するため、"use client"ディレクティブが必要である。
- また、フォームの送信やユーザーインタラクションを処理するために、このコンポーネントはクライアントサイドで動作する必要がある。
- 結論として、"use client"ディレクティブを追加することで、LoginPageコンポーネントとその中で使用されているフックやイベントハンドラーがクライアントサイドで正しく動作するようになり、エラーが解決される。
このスクラップは2ヶ月前にクローズされました