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

React组件中绑定的登录函数为何每次输入都会自动触发?

问题成因

你在为按钮绑定onClick事件时,直接写入了loginRequest(username, password)这个函数调用表达式,而非待触发的函数引用。
React组件每次执行渲染(包含首次挂载渲染、state更新触发的重渲染)时,都会先计算JSX中所有属性的表达式值:这行函数调用会在渲染阶段直接执行,拿到返回值后再绑定给onClick属性,完全不会等待用户点击按钮后再触发。

  • 页面首次加载时组件完成第一次渲染,直接触发一次登录请求
  • 输入框输入内容会更新对应state,触发组件重渲染,每重渲染一次就会执行一次函数调用,最终出现逐字符发送登录请求的现象
    另外你代码中密码输入框的type属性设置为了text,输入内容会明文展示,属于配套的易用性问题。
修复方案

有两种符合React事件绑定规范的写法,可以实现仅点击按钮时才触发请求的效果:

写法1:箭头函数包裹调用逻辑

在onClick属性中传入一个箭头函数作为事件回调,将登录请求的调用逻辑放在箭头函数内部,只有点击事件触发时才会执行内部代码:

<Button 
  onClick={() => loginRequest(username, password)}
  className='withdraw-deposit-button'
>
  Login/Deposit
</Button>

同时将密码输入框的type属性修正为password,隐藏输入的明文内容:

<input 
  type="password"
  placeholder="Password"
  onChange={e => changePassword(e.target.value)}
  value={password}
/>

写法2:直接读取组件内state,传递函数引用

修改loginRequest函数逻辑,不需要通过参数传递账号密码,直接读取组件作用域内的username和password状态值,绑定事件时直接传入函数引用(不要加括号执行)即可,这种写法不需要每次渲染都创建新的箭头函数,性能更优:

const loginRequest = async () => {
  // 直接读取组件内的state,无需额外传参
  const response = await service.loginRequest(username, password);
  console.log(response);
}

// 绑定事件时直接传入函数名
<Button 
  onClick={loginRequest}
  className='withdraw-deposit-button'
>
  Login/Deposit
</Button>
修正后完整代码
import { useState } from 'react';
// 需根据项目实际路径引入Card、Button组件与service请求模块

function LoginPage() {
    const [username, changeUsername] = useState('');
    const [password, changePassword] = useState('');

    const loginRequest = async () => {
        const response = await service.loginRequest(username, password);
        console.log(response);
    }

    return (
        <Card hoverable className='transaction-button-card'>
            <h1>Enter username and password</h1>
            <input 
                type="text"
                placeholder="Username"
                onChange={e => changeUsername(e.target.value)}
                value={username}
            />
            <input 
                type="password"
                placeholder="Password"
                onChange={e => changePassword(e.target.value)}
                value={password}
            />
            <Button 
                onClick={loginRequest}
                className='withdraw-deposit-button'
            >
                Login/Deposit
            </Button>
        </Card>
    );
}

export default LoginPage;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 02:54:24