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

React.js中FormControl无法更新状态值的问题排查

Hey there! Let's break down what's going wrong with your login component and fix it step by step.

What's Causing the Issue?

You've got two main problems here that are keeping your state from updating correctly:

  1. Incorrect onChange Event Parameters
    React's form input components (including React Bootstrap's FormControl) pass only a single event object to the onChange callback—there's no second newValue argument. Right now, you're trying to use newValue which is undefined, so when you call setState({email: newValue}), you're actually setting the state to undefined (which still matches your empty string check later).

  2. Premature Function Call in catch
    Your .catch(this.badInfosAlert('An error happend')) line is immediately running the badInfosAlert function when the component mounts, not when an error is caught. That's because you're invoking the function directly instead of passing a callback.

Plus, while your onClick arrow function does bind this correctly for handleSubmit, we can clean that up too.

Step-by-Step Fixes

1. Fix the onChange Handlers

Update both FormControl elements to pull the input value from event.target.value instead of looking for a newValue parameter:

<FormControl 
  type="email" 
  onChange={(event) => this.setState({email: event.target.value})} 
  placeholder="Email" 
/>

<FormControl 
  type="password" 
  onChange={(event) => this.setState({password: event.target.value})} 
  placeholder="Password" 
/>

(Note: I also changed the email input's type to "email" for better native validation—optional but recommended!)

2. Fix the catch Callback

Replace your current catch block with an arrow function so the alert only runs when an error occurs:

.catch(() => this.badInfosAlert('An error happened'));

3. (Optional) Simplify this Binding

Instead of wrapping handleSubmit in an arrow function in the onClick, you can define handleSubmit as an arrow function directly in the class. This ensures this always refers to the component instance:

handleSubmit = (event) => {
  // Your existing handleSubmit code here
}

Then update the Button to use the method directly:

<Button onClick={this.handleSubmit}>Login</Button>

Full Fixed Component Code

Here's the complete corrected component with all the fixes applied:

import React from 'react'
import { login } from '../../api/Authentication'
import { setStore } from '../../webapp/storage'
import { Button, ControlLabel, Form, FormControl, FormGroup } from 'react-bootstrap';

export default class LoginPage extends React.Component {
  constructor(props){
    super(props);
    this.state={
      email:'',
      password:''
    }
  }

  handleSubmit = (event) => {
    // Prevent default form submission behavior
    event.preventDefault();
    
    if (this.state.email === '' || this.state.password === '') {
      const message = this.state.email === '' ? 'Email field empty' : 'Password field empty';
      this.badInfosAlert(message);
      return;
    }
    
    console.log('-----------------------')
    console.log(this.state.email)
    console.log(this.state.password)
    const user = {
      email: this.state.email,
      password: this.state.password
    }
    console.log(JSON.stringify(user))
    console.log('-----------------------')
    
    login(user).then(result => {
      if (result != null && result.status === 200) {
        setStore('token', result.json.user.token)
      } else {
        this.badInfosAlert(result.json.error)
      }
    }).catch(() => this.badInfosAlert('An error happened'));
  }

  badInfosAlert(message) {
    console.log(message);
    alert(message);
  }

  render() {
    return (
      <div className='col-lg-12'>
        <Form onSubmit={this.handleSubmit}>
          <FormGroup controlId="formHorizontalEmail">
            <ControlLabel>Email </ControlLabel>
            <FormControl 
              type="email" 
              value={this.state.email} // Add controlled input binding (optional but best practice)
              onChange={(event) => this.setState({email: event.target.value})} 
              placeholder="Email" 
            />
          </FormGroup>

          <FormGroup controlId="formHorizontalPassword">
            <ControlLabel>Password </ControlLabel>
            <FormControl 
              type="password" 
              value={this.state.password} // Add controlled input binding
              onChange={(event) => this.setState({password: event.target.value})} 
              placeholder="Password" 
            />
          </FormGroup>

          <Button type="submit">Login</Button>
        </Form>
      </div>
    )
  }
}

I also added a couple of extra improvements:

  • event.preventDefault() in handleSubmit to stop the browser from reloading the page when the form submits
  • Added value={this.state.email} and value={this.state.password} to make the inputs fully controlled (this ensures the input always reflects the state value, which is a React best practice)
  • Changed the Button's type to "submit" and added onSubmit to the Form instead of using a click handler—this is more semantic for form submissions

Quick Recap

  • Always get input values from event.target.value in React form onChange handlers
  • Never invoke callback functions directly in .catch()—use an arrow function to delay execution
  • Use controlled inputs (bind the value prop to state) for predictable form behavior

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:37:16