【问题标题】:NEXTJS: Invalid hook callNEXTJS: 无效的钩子调用
【发布时间】:2022-01-08 17:42:02
【问题描述】:

我正在使用 nextjs 12 中的新中间件,并尝试使用 firebase 添加身份验证。

但是当我尝试使用钩子 useAuthState 时,它给了我一个错误消息:“无效的钩子调用。只能在函数组件的主体内部调用钩子。这可能由于以下原因之一发生:

  1. 您可能有不匹配的 React 版本和渲染器(例如 React DOM)
  2. 您可能违反了 Hooks 规则
  3. 您可能在同一个应用程序中拥有多个 React 副本 有关如何调试和修复此问题的提示,请参阅 https://reactjs.org/link/invalid-hook-call。 空”

除了在 pages 目录中创建 2 个组件之外,我没有对应用程序进行任何更改

login.js 和 _middleware.js

这是我的 _middleware.js

import { NextResponse } from "next/server";
// import firebase from "firebase"
import { initializeApp } from "firebase/app";
import "firebase/auth";
import { getAuth } from "firebase/auth";
import { useAuthState } from "react-firebase-hooks/auth";

initializeApp({ ... });

const auth = getAuth();

export async function middleware(req) {
  const [user] = useAuthState(auth);
  const { pathname } = req.nextUrl;

  if (!user) {
    return NextResponse.redirect("/login");
  }

  return NextResponse.next();
}

这是我的 login.js

function login() {
  const signInWithGoogle = () => {
    console.log("Clicked!");
  };

  return (
    <div>
      <button onClick={signInWithGoogle}>Sign in with google</button>
    </div>
  );
}

export default login;

这是我的 package.json

{
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "firebase": "^9.5.0",
    "next": "^12.0.4",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-firebase-hooks": "^4.0.1"
  },
  "devDependencies": {
    "autoprefixer": "^10.2.6",
    "postcss": "^8.3.5",
    "tailwindcss": "^2.2.4"
  }
}

【问题讨论】:

  • 你在反应组件之外调用了一个钩子useAuthState

标签: reactjs firebase react-hooks next.js


【解决方案1】:

根据React docs

不要从常规 JavaScript 函数调用 Hook。 相反,您可以:

✅ 从 React 函数组件调用 Hooks。
✅ 从自定义 Hooks 调用 Hooks(我们将在下一页了解它们)。

所以您在下面的常规 Javascript 函数中使用 钩子

export async function middleware(req) { // this is regular JavaScript function
  const [user] = useAuthState(auth); // here you're using hook
  const { pathname } = req.nextUrl;

  if (!user) {
    return NextResponse.redirect("/login");
  }

  return NextResponse.next();
}

解决方案您的情况可能是

import React, { useEffect } from "react";
import { NextResponse } from "next/server";
import { useAuthState } from "react-firebase-hooks/auth";

function login() {
  const [user] = useAuthState(auth); // here you're using hook
  const { pathname } = req.nextUrl;
  
  useEffect(() => {
    if (!user) {
      return NextResponse.redirect("/login");
    }
  
    return NextResponse.next();
  }, [user]);

  const signInWithGoogle = () => {
    console.log("Clicked!");
  };


  return (
    <div>
      <button onClick={signInWithGoogle}>Sign in with google</button>
    </div>
  );
}

export default login;

不要忘记在组件中导入所需的导入

【讨论】:

  • 嘿,我刚看到你回答,我注意到代码的第二个 sn-p 用于 login.js,虽然这可能有效,但我正在尝试使用中间件,以便我可以检查用户是否在访问任何页面之前是否已登录,即使在 login.js 上尝试了新代码之后,它也会给我一个错误,说 SyntaxError: Unexpected token 'export'
【解决方案2】:

关注 nextjs documentation:

下一个/服务器

next/server 模块为 server-only 助手提供了几个导出,例如Middleware

中间件

中间件使您能够使用代码而不是配置。这为您在 Next.js 中提供了充分的灵活性,因为您可以在请求完成之前运行代码。根据用户的传入请求,您可以通过重写、重定向、添加标头甚至流式 HTML 来修改响应。

中间件不是 react 组件,不能使用 hooks。

【讨论】:

    猜你喜欢
    • 2021-08-11
    • 2020-12-18
    • 2021-08-09
    • 1970-01-01
    • 1970-01-01
    • 2020-12-02
    • 1970-01-01
    • 2020-04-21
    • 1970-01-01
    相关资源
    最近更新 更多