You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React项目中TypeError: login is not a function错误排查求助

解决React AuthContext中TypeError: login is not a function错误

核心问题分析

你的代码存在三个关键问题导致该错误:

  • useAuth钩子实现错误:当前钩子未使用React的useContext获取上下文值,而是通过参数接收,完全违背Context的使用逻辑,导致Login组件无法拿到真正的login函数。
  • App组件在AuthProvider外部调用useAuth:App是AuthProvider的父组件,在其内部调用useAuth无法获取Context值,因为Context作用域仅覆盖Provider包裹的子组件。
  • Login组件调用login时参数缺失:login函数需要email和password两个参数,但handleSubmit中只传了email,不仅会导致后端验证失败,也是潜在的逻辑漏洞。

修复步骤

1. 修正useAuth钩子实现

修改authContext.js,让useAuth通过useContext正确获取上下文:

import React, { createContext, useState, useContext } from 'react';
import axios from 'axios';

const AuthContext = createContext();

export function AuthProvider({ children }) {
  const [userAuthenticated, setUserAuthenticated] = useState(false);

  const API = process.env.REACT_APP_API_URL;

  const login = async (email, password) => {
    try {
      console.log('Intentando iniciar sesión con email:', email, password);
      const response = await axios.post(`${API}users/login/`, { email, password });
      if (response.data.isAuthenticated) {
        setUserAuthenticated(true);
        return true;
      } else {
        return false;
      }
    } catch (error) {
      console.error('Error en el inicio de sesión:', error);
      return false;
    }
  };

  const logout = () => {
    setUserAuthenticated(false);
  };

  return (
    <AuthContext.Provider value={{ userAuthenticated, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
}

export function useAuth() {
  return useContext(AuthContext);
}

2. 修复App组件的路由保护逻辑

创建独立的受保护路由组件,替代在App组件中直接判断用户状态:

// 新建components/ProtectedRoute.js
import { Navigate } from 'react-router-dom';
import { useAuth } from './authContext';

export default function ProtectedRoute({ children }) {
  const { userAuthenticated } = useAuth();
  return userAuthenticated ? children : <Navigate to="/login" />;
}

修改App.js,移除内部的useAuth调用,改用ProtectedRoute保护/dashboard路由:

import './App.css';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import { useState, useEffect } from 'react';
import axios from 'axios';

import { AuthProvider } from './components/authContext';
import { CartProvider } from './products/cartContext'; 
import ProtectedRoute from './components/ProtectedRoute';

import CompShowProducts from './products/products';
import CompCreateProduct from './products/createProduct';
import CompEditProduct from './products/editProduct';

import Login from './components/login'

import Header from './components/header';
import Footer from './components/footer';

import Home from './components/home';
import SearchResultPage from './components/searchResultPage';
import ProductGrid from './products/productGrid';
import MayoristaProductGrid from './products/mayProductGrid';
import ShoppingCart from './products/cart';
import AboutUs from './components/aboutUs';
import CategoryProducts from './products/categoryProducts';
import LocalLocations from './components/branches';
import ContactButton from './components/contactButton';
import GoToShopButton from './components/goToShopButton';

function App() {
  const [products, setProducts] = useState([]);
  const [brands, setBrands] = useState([]);
  const [categories, setCategories] = useState([]);
  const [searchResults, setSearchResults] = useState([]);
  
  const API = process.env.REACT_APP_API_URL;
  const productsAPI = `${API}products/`;

  axios.defaults.withCredentials = true;

  useEffect(() => {
    const fetchProducts = async () => {
      try {
        const response = await axios.get(productsAPI);
        setProducts(response.data);

        const uniqueBrands = [...new Set(response.data.map((product) => product.brand))];
        setBrands(uniqueBrands);

        const uniqueCategories = [...new Set(response.data.map((product) => product.category.name))];
        setCategories(uniqueCategories);
      } catch (error) {
        console.error('Error al obtener los datos:', error);
      }
    };

    fetchProducts();
    // eslint-disable-next-line
  }, []);

  return (
    <AuthProvider>
    <CartProvider>
      <div className="App">
        <BrowserRouter>
          <Header setSearchResults={setSearchResults} />
          <Routes>
            <Route path='/' element={<Home />} />
            <Route path="/productos" element={
              <ProductGrid
                products={products}
                brands={brands}
                categories={categories}
              />
            } />
            <Route path="/mayorista" element={
              <MayoristaProductGrid
                products={products}
                brands={brands}
                categories={categories}
              />
            } />
            <Route path='/cart' element={<ShoppingCart />} />
            <Route path="/dashboard" element={
              <ProtectedRoute>
                <CompShowProducts />
              </ProtectedRoute>
            } />
            <Route path="/create" element={<CompCreateProduct />} />
            <Route path="/edit/:id" element={<CompEditProduct />} />
            <Route path="/search-results" element={<SearchResultPage searchResults={searchResults} />} />
            <Route path="/aboutus" element={< AboutUs />} />
            <Route path="/productos/:category" element={<CategoryProducts />} />
            <Route path="/sucursales" element={<LocalLocations />} />
            <Route path="/login" element={<Login />} />
          </Routes>
          <GoToShopButton/>
          <ContactButton/>
        </BrowserRouter>
        <Footer />
      </div>
    </CartProvider>
    </AuthProvider>
  );
}

export default App;

3. 修复Login组件的login参数传递

修改Login组件的handleSubmit,同时传入email和password:

const handleSubmit = async (e) => {
  e.preventDefault();
  console.log('handleSubmit iniciado');
  const isAuthenticated = await login(email, password);
  if (isAuthenticated) {
    console.log('Redirigiendo a /dashboard');
    navigate('/dashboard');
  } else {
    setError('Autenticación fallida');
  }
};

验证修复

  1. 重启React应用
  2. 尝试登录,此时login函数可正常获取Context中的实现,不会再出现login is not a function错误
  3. 登录成功后会正确跳转到/dashboard,未登录时访问/dashboard会被重定向到/login

内容的提问来源于stack exchange,提问作者Dante Costamagna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 10:02:33