我有一个对一个工作良好的API的前端调用:

  const handleSubmit = async (e: any) => {
    e.preventDefault();
    setLoading((loading) => !loading);
    setResult('');
    const login = useRouterseUser()
    console.log('submitted form')
    try {
      // login= useUser() //the substitute i'de like to make//
       //  login(email,password)//subsitute i'de like to make for the api call below\\

      
      const response = await axios.post('/api/login', {email, password} ) // Send as query paramers );
      setIsloggedin(()=> true)

      router.replace('/dashboard')
      
    } catch (error) {
      alert(JSON.stringify(error.response.data.detail));
    }
    finally{
      setLoading((loading) => !loading)
    }
  }

然而,我创建了另一个文件来从usecontext挂钩内进行api调用,这样我就可以使用响应作为整个应用程序的全局可用变量.为此,我在上下文中定义了一个函数,并将应用程序包装在上下文提供者中,如下所示:

export default function RootLayout({children}: { children: React.ReactNode}) {
  return (
    <html lang="en">

      <body className={inter.className}>
        <UserProvider>{children}</UserProvider>
        
        
        </body>
    </html>
  )
}

该调用不起作用,它无法访问API,因为上下文不可用. 上下文页面如下:

'use client'

import { ID } from "appwrite";
import { createContext, useContext, useEffect, useState } from "react";
import { account } from '../appwrite'
  
const UserContext = createContext();

export function UserProvider(props) {
  const [user, setUser] = useState(null);

  async function login(email, password) {
    
    const loggedIn = await axios.post('/api/login', {email, password} )
    setUser(loggedIn);
  }
    

  async function register (email, password, name) {
   await axios.post('/api/signup', { email,  password, name} );

  }  

  async function logout() {
    await axios.post('/api/currentuser');
   // await account.deleteSession("current");
    setUser(null);
  }

  async function init() {
    try {
      const loggedIn = await account.get();
      setUser(loggedIn);
    } catch (err) {
      setUser(null);
    }
  }

  useEffect(() => {
    init();
  }, []);

  return (
    <UserContext.Provider value={{ current: user, login, logout, register }}>
      {props.children}
    </UserContext.Provider>
  );
}
export function useUser() {
  return useContext(UserContext) ;
}

我收到一个错误,指出上面的useuser()函数输出是: 错误:无效的挂钩调用.Hooks只能在功能组件的体内调用.这种情况可能出于以下原因之一发生:

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

有人能帮忙吗?我觉得我想做的事情很简单.

推荐答案

问题是代码正在调用回调函数中的useUseruseRouterseUser挂钩,这违反了挂钩规则.必须在组件的顶层调用React挂钩.

解决方案是将这些挂钩调用移至提交处理程序回调之外.

const Login = () => {
  const router = useRouter();
  const { login } = useUser();

  ...

  const handleSubmit = async (e: any) => {
    e.preventDefault();

    setLoading(true);
    setResult('');
    
    try {
      await login(email, password);
      setIsloggedin(true);
      router.replace('/dashboard');
    } catch (error) {
      alert(JSON.stringify(error.response.data.detail));
    } finally {
      setLoading(false);
    }
  };

  ...
};

Reactjs相关问答推荐

从app.js导航,这是在BrowserRouter包装之外

一键MUI导出

在REACT-RUTER-DOMV6中使用通用页面包装组件有问题吗?

react 挂钩-使用有效澄清

为什么我得不到我想要的数据?

使用VITE的Reaction应用程序的配置是否正确?

我在Route组件上使用元素属性,这样就不需要ID了吗?

如何获取用户在 GooglePlacesAutocomplete 中输入的文本?

如何修复ReferenceError:在构建过程中未定义导航器

在 Next13 中将 props 传递给 onClick 从服务器到客户端组件

如果我使用 formik,如何在嵌套对象中写入正确的值?

修改React数据表扩展组件

React - 函数组件 - 点击两次问题处理

需要先填写依赖输入字段,以便其他人工作

使用带有搜索字符串的全局过滤器时如何在 React-Table 中进行精确匹配?

需要在窗口调整大小时更新 React 组件

无法重用我的组件,它只显示 1 次

为什么 React 会多次调用我的应用程序的某些函数?

试图将页面限制为仅登录但有条件的用户似乎永远不会运行

useEffect 仅在跟随链接后有效,不适用于直接链接