reactjs 在表单提交时更改状态时响应Axios挂起

qhhrdooz  于 2023-01-02  发布在  React
关注(0)|答案(1)|浏览(107)

我尝试提交一个登录页面,在请求处理过程中,登录表单被禁用。如果我提交了不正确的凭据,表单会按预期禁用,请求会被发送,一旦返回401,表单会再次启用。但是如果我尝试使用不同的凭据再次提交,axios请求会挂起。而且承诺永远不会解决。我的浏览器标签挂起,我不得不关闭它。
下面是登录页面的代码:

import React, { useState } from 'react';
import { useNavigate, NavigateFunction } from 'react-router-dom';
import { MailOutlined, KeyOutlined } from '@ant-design/icons';
import { Button, Form, Input, Typography } from 'antd';
import Navbar from '../components/Navbar';
import { DASHBOARD_ROUTE } from '../data/constants';
import styles from './Login.module.css';
import axios from 'axios';

export interface LoginProps {}

interface LoginCredentials {
  usernameOrEmail: string,
  password: string,
}

const { Title } = Typography;

// login page
const Login = (props: LoginProps): JSX.Element | null => {
  const [passwordVisible, setPasswordVisible] = useState<boolean>(false);
  const [loginDisabled, setLoginDisabled] = useState<boolean>(false);
  const navigate: NavigateFunction = useNavigate();

  const handleLogin = (credentials: LoginCredentials): void => {
    if (loginDisabled) {
      return;
    }

    setLoginDisabled(true);
    axios.post(
      '/accounts/jwt/create/',
      {
        username: credentials.usernameOrEmail,
        password: credentials.password
      },
      {
        baseURL: 'http://localhost:8000',
        headers: {
          'Content-Type': 'application/json'
        }
      }
    ).then(() => navigate(DASHBOARD_ROUTE)
    ).catch((err: any) => {
      console.log(err);
      setLoginDisabled(false);
    });
  };

  return (
    <div>
      <Navbar selectedKey='login'>
        <div className={styles.mainContainer}>
          <Title>Login</Title>
          <Form
            name='basic'
            layout={'vertical'}
            initialValues={{ remember: true }}
            onFinish={handleLogin}
            disabled={loginDisabled}
          >
            <Form.Item
              label='Username/Email'
              name='usernameOrEmail'
              rules={[{ required: true, message: 'Please enter your username/email' }]}
            >
              <Input
                name="usernameOrEmail"
                placeholder='Enter username/email'
                prefix={<MailOutlined />}
              />
            </Form.Item>
            <Form.Item
              label='Password'
              name='password'
              rules={[{ required: true, message: 'Please enter your password' }]}
            >
              <Input.Password
                name="password"
                placeholder='Enter password'
                prefix={<KeyOutlined />}
                visibilityToggle={{ visible: passwordVisible, onVisibleChange: setPasswordVisible }}
              />
            </Form.Item>
            <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
              <Button
                type='primary'
                htmlType='submit'
              >
                Login
              </Button>
            </Form.Item>
          </Form>
        </div>
      </Navbar>
    </div>
  );
}

export default Login;

我期望的工作方式是,在handleLogin发送请求之前,loginDisabled钩子将被设置为true,这将把表单的disabled属性设置为true,然后,axios请求将被发送,一旦请求返回,loginDisabled将被再次设置为false,这样表单将再次可用。
不知何故,如果我尝试登录两次,UI就会冻结,axios请求永远不会完成。我可以在后端看到请求通过并得到响应,axios请求拦截器被触发,但axios * 响应 * 拦截器从未被触发。我知道通常情况下我应该有一个超时,但这不应该发生在任何地方。我想我把钩子的某个地方搞砸了。
我收集了一些东西:

  • 后端工作正常,事实上,不管axios在哪里发送请求,它总是冻结
  • 如果我删除setLoginDisabled函数调用,整个问题就完全消失了。当然,这意味着表单永远不会被禁用。

你知道这是怎么回事吗?任何形式的帮助都很感激,谢谢!

1cosmwyk

1cosmwyk1#

弄明白了是怎么回事:Navbar组件实际上还依赖于用户的身份验证状态,这在某些地方会导致无限循环。2删除(或者说重构)Navbar对我来说就是这样。

相关问题