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

React按钮onClick异常:输入框误触发或点击无响应问题排查

React登录组件问题排查与修复

核心问题分析

1. Button组件未传递点击事件

自定义Button组件没有接收onClick属性,也未绑定到内部原生button元素,导致父组件传入的点击处理函数完全无法触发。

2. 错误在普通函数中使用React Hook

useState是React Hook,仅能在函数式组件或自定义Hook中调用,不能在普通工具函数OnLogin内使用。

3. 异步请求逻辑错误

axios请求是异步操作,TestToken内的return语句不会等待请求完成就执行,直接返回undefined,导致后续判断永远走else分支;同时POST请求参数格式错误,{username: {username}}会生成嵌套对象,不符合后端预期格式。

4. 函数命名混淆

普通函数建议小写开头(如onLogin而非OnLogin),避免与首字母大写的React组件命名规范冲突。


分步修复代码

修复Button组件

让组件接收并传递onClick属性:

import React from "react";
import styled from "styled-components";

const Button = ({text, onClick}) => {
  return (
    <StyledWrapper>
      {/* 将onClick绑定到原生button */}
      <button className="animated-button" onClick={onClick}>
        <svg
          viewBox="0 0 24 24"
          className="arr-2"
          xmlns="http://www.w3.org/2000/svg"
        >
          <path d="M16.1716 10.9999L10.8076 5.63589L12.2218 4.22168L20 11.9999L12.2218 19.778L10.8076 18.3638L16.1716 12.9999H4V10.9999H16.1716Z" />
        </svg>
        <span className="text">{text}</span>
        <span className="circle" />
        <svg
          viewBox="0 0 24 24"
          className="arr-1"
          xmlns="http://www.w3.org/2000/svg"
        >
          <path d="M16.1716 10.9999L10.8076 5.63589L12.2218 4.22168L20 11.9999L12.2218 19.778L10.8076 18.3638L16.1716 12.9999H4V10.9999H16.1716Z" />
        </svg>
      </button>
    </StyledWrapper>
  );
};

const StyledWrapper = styled.div`
  .animated-button {
  position: relative;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 16px 36px;
  border: 4px solid;
  border-color: transparent;
  font-size: 16px;
  background-color: inherit;
  border-radius: 100px;
  font-weight: 600;
  color: greenyellow;
  box-shadow: 0 0 0 2px greenyellow;
  cursor: pointer;
  overflow: hidden;
  transition: all 0.6s cubic-bezier(0.23, 1, 0.32, 1);
}

.animated-button svg {
  position: absolute;
  width: 24px;
  fill: greenyellow;
  z-index: 9;
  transition: all 0.8s cubic-bezier(0.23, 1, 0.32, 1);
}

.animated-button .arr-1 {
  right: 16px;
}

.animated-button .arr-2 {
  left: -25%;
}

.animated-button .circle {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 20px;
  height: 20px;
  background-color: greenyellow;
  border-radius: 50%;
  opacity: 0;
  transition: all 0.8s cubic-bezier(0.23, 1, 0.32, 1);
}

.animated-button .text {
  position: relative;
  z-index: 1;
  transform: translateX(-12px);
  transition: all 0.8s cubic-bezier(0.23, 1, 0.32, 1);
}

.animated-button:hover {
  box-shadow: 0 0 0 12px transparent;
  color: #212121;
  border-radius: 12px;
}

.animated-button:hover .arr-1 {
  right: -25%;
}

.animated-button:hover .arr-2 {
  left: 16px;
}

.animated-button:hover .text {
  transform: translateX(12px);
}

.animated-button:hover svg {
  fill: #212121;
}

.animated-button:active {
  scale: 0.95;
  box-shadow: 0 0 0 4px greenyellow;
}

.animated-button:hover .circle {
  width: 220px;
  height: 220px;
  opacity: 1;
}

`;

export default Button;

修复Login组件的登录逻辑

将登录逻辑改为组件内部异步函数,修正参数格式与异步流程:

import React, { useState } from 'react';
import './Login.css';
import Button from './button';
import axios from 'axios';

// 改为异步函数,返回验证结果的Promise
async function testToken(token) {
  try {
    const response = await axios.get('http://localhost:8000/login/test_token', {
      headers: {
        Authorization: 'Token ' + token
      }
    });
    console.log(response.data);
    return true;
  } catch (error) {
    console.log(error + ", token authentication failed!");
    return false;
  }
};

export function Login() {
    const [username, setUsername] = useState("");
    const [password, setPassword] = useState("");
    const [token, setToken] = useState(""); // 将token状态移至组件内部

    function getUser(event) {
        setUsername(event.target.value);
    }

    function getPassword(event) {
        setPassword(event.target.value);
    }

    // 组件内部异步登录处理函数
    const handleLogin = async () => {
        console.log("Handle activated");
        try {
          // 修正POST参数格式,避免嵌套
          const response = await axios.post('http://localhost:8000/login', {
            username: username,
            password: password
          });
          const newToken = response.data.token;
          setToken(newToken);
          console.log(response.data.user);
          
          // 等待token验证完成后再判断登录状态
          const isTokenValid = await testToken(newToken);
          isTokenValid ? console.log("Logged in!") : console.log("Log in failed!");
        } catch (error) {
          console.log(error);
        }
        console.log("Login process concluded!");
    }

    return(
        <div className= "functional-box">
        <div className= "login-page">
        <div className= "login-title">Log In</div>
        <div className= "inputs">
            <input className= "input-text" onChange={getUser} type="text" placeholder='Username'/>
            <input className= "input-text" onChange={getPassword} type="password" placeholder="Password"/>
        </div>
        <div className="button-div"><Button className="login-button" text="Login" onClick={handleLogin}></Button></div>
        </div>
        </div>
    );
}

export default Login;

修复说明

  1. Button组件现在会接收并传递onClick属性,点击事件可正常触发。
  2. 登录逻辑改为组件内部异步函数,符合React Hook使用规则,用async/await确保异步操作顺序正确。
  3. 修正POST请求参数格式,直接传递用户名和密码,避免嵌套对象。
  4. testToken改为异步函数,等待请求结果后再判断登录状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 10:17:03