首页 > 解决方案 > 用于用户身份验证的反应上下文:使用正确的凭据登录时“TypeError:setUser 不是函数”

问题描述

我无法弄清楚为什么会出现此错误:

TypeError:setUser 不是函数 login.js:43

postLogin login.js:39

尝试使用正确的用户凭据登录时。setUser 显然是一个函数,因为它取自 auth.js 中的 useAuth()。我在这个登录过程中使用了 React Context、会话存储、Flask 和 sqlite。

auth.js:

import { createContext, useContext, useState } from "react";

export const AuthContext = createContext();

export const AuthProvider = function({ user, children }) {
    const [currentUser, setCurrentUser] = useState(user);

    const setAuth = (data) => {
        sessionStorage.setItem('username', data.user.username);
        sessionStorage.setItem('isAdmin', data.user.isAdmin);
        setCurrentUser(data.user);
    }

    return (
        <AuthContext.Provider value={{ currentUser, setCurrentUser: setAuth }}>
            {children}
        </AuthContext.Provider>
    )
}

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

应用程序.js:

import { useState, useEffect } from "react";
import { BrowserRouter as Router } from "react-router-dom";
import { AuthProvider, useAuth } from './context/auth';
import "bootstrap/dist/css/bootstrap.min.css";

/* Begin Import Components */
import NavigationBar from "./components/navbar";
import Public from "./components/public-components/public";
/* End Import Components */

function App(props) {
  const user = useAuth();

  return (
    <AuthProvider user={user}>
      <Router>
        <NavigationBar />
        <div className="container text-center">
          <Public />
        </div>
      </Router>
      </AuthProvider>
  );
}

export default App;

登录.js:

import { useState } from "react";
import { Link, Redirect } from 'react-router-dom';
import { useAuth } from '../../context/auth';
import { Col, Form, Row, Button } from 'react-bootstrap';

function Login(props) {
    const [loggedIn, setLoggedIn] = useState(false);
    const [isError, setIsError] = useState(false);
    const [email, setEmail] = useState("");
    const [password, setPassword] = useState("");
    const { setUser } = useAuth();

    let referer;
    if(props.location.state !== undefined) {
        referer = props.location.state.referer;
    } else {
        referer = "/";
    }

    function postLogin() {
        const formData = new FormData();
        formData.append('email', email);
        formData.append('password', password);

        fetch('/login', {
            method: 'post',
            body: formData
        }).then(res => res.json())
        .then(data => {
            console.log('Login response data: ', data);
            if(data.wrongPassword) {
                setIsError(true);
            } else {
                setUser({username: data.user.username, isAdmin: data.user.isAdmin});
                setLoggedIn(true);
            }
        }).catch(err => {
            console.log(err);
            setIsError(true);
        });;
    }

    if(loggedIn) {
        return <Redirect to={referer} />;
    }

    return (
        <main>
            <header>
                <h2>Login</h2>
            </header>
            <section>
                <Form>
                    <Row className="justify-content-sm-center">
                        <Form.Group as={Col} sm={{ span: 6 }}>
                            <Form.Label htmlFor="email">Email</Form.Label>
                            <Form.Control
                                        controlid="email"
                                        type="email"
                                        value={email}
                                        onChange={e => {
                                            setEmail(e.target.value);
                                        }}
                                        placeholder="Enter email"
                                        autoFocus
                                        />
                        </Form.Group>
                    </Row>
                    <Row className="justify-content-sm-center">
                        <Form.Group as={Col} sm={{ span: 6 }}>
                            <Form.Label htmlFor="password">Password</Form.Label>
                            <Form.Control
                                        controlid="password"
                                        type="password"
                                        value={password}
                                        onChange={e => {
                                            setPassword(e.target.value);
                                        }}
                                        placeholder="Enter password"
                                        />
                        </Form.Group>
                    </Row>
                    <Button onClick={postLogin} variant="success">Login</Button>
                </Form>
            </section>
            <Link to="/register">Don't have an account?</Link>
            { isError &&<p>There was a problem logging in!</p> }
        </main>
    )
}

export default Login;

来自 Flask 后端(api.py)的登录路径:

@app.route("/login", methods=['POST'])
def login():
    try:
        email = request.form['email']
        password = request.form['password']

        user = db.session.query(User.username, User.password).filter_by(email=email).first()
        user_role = db.session.query(UserRole.role).filter_by(username=user.username).first()

        if(check_password_hash(user.password, password)):
            if(user_role.role == 'Admin'):
                return {'user': {'username': user.username, 'isAdmin': True}}
            return {'user': {'username': user.username, 'isAdmin': False}}
        else:
            return {'wrongPassword':True}
    except:
        return 'Something went wrong...'

标签: javascriptreactjsreact-contextsession-storage

解决方案


您将变量命名为:setCurrentUsersetUser不到:

        <AuthContext.Provider value={{ currentUser, setCurrentUser: setAuth }}>

所以没有setUser从提供者返回


推荐阅读