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

React-Redux密码强度条失效求助:如何正确绑定事件监听器

Fixing Password Strength Bar in Your React Component

Hey there! Let's get that password strength bar working properly. I spotted a few issues in your code that are holding this back—let's walk through them and fix things step by step.

Key Issues in Your Current Code

  • Direct DOM operations in class scope: You tried to use getElementById and addEventListener directly in the class body, which runs before the component mounts. At that point, the DOM elements don't exist yet, so this will throw errors.
  • Incorrect function placement: checkPassword was defined outside the class methods, which isn't valid syntax for React class components.
  • Missing DOM ID: Your password input didn't have the id="password" you were trying to target.
  • Uncontrolled progress bar: You were manually updating the progress bar's value via DOM instead of using React state, which breaks React's data flow.

Fixed Code with Explanations

Here's the updated version of your component, with all the fixes and the password strength bar working as intended:

import React from 'react'
import { connect } from 'react-redux'
import { registerUserRequest } from '../../actions/register'
import { loginError } from '../../actions/login'

class Register extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      user_name: '',
      contact_number: '',
      email_address: '',
      password: '',
      confirm_password: '',
      passwordStrength: 0 // Add state to track password strength
    }
    this.updateDetails = this.updateDetails.bind(this)
    this.submit = this.submit.bind(this)
    this.validateEmail = this.validateEmail.bind(this)
    this.validatePassword = this.validatePassword.bind(this)
    this.checkPasswordStrength = this.checkPasswordStrength.bind(this) // Bind our new method
  }

  componentDidMount() {
    this.props.dispatch(loginError(''))
  }

  updateDetails(e) {
    const { name, value } = e.target
    this.setState({ [name]: value }, () => {
      // If we're updating the password, calculate its strength after state updates
      if (name === 'password') {
        this.checkPasswordStrength(value)
      }
    })
  }

  submit(e) {
    e.preventDefault()
    e.target.reset()
    let { user_name, password, confirm_password, email_address, contact_number } = this.state

    const passwordsMatch = confirm_password === password
    const isEmailValid = this.validateEmail(email_address)
    const isPasswordValid = this.validatePassword(password)

    if (!isEmailValid || !passwordsMatch) {
      return this.props.dispatch(loginError("Incorrect email/Passwords don't match"))
    } else if (!isPasswordValid) {
      return this.props.dispatch(loginError('Password must be 8+ characters and include at least one number'))
    } else {
      return this.props.dispatch(registerUserRequest(this.state))
    }
  }

  validateEmail(email) {
    const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
    return re.test(String(email).toLowerCase())
  }

  validatePassword(pass) {
    const re = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/
    return re.test(String(pass))
  }

  // New method to calculate password strength and update state
  checkPasswordStrength(password) {
    let strength = 0

    // Adjust strength based on different criteria
    if (password.match(/[a-zA-Z0-9]{2,}/)) strength += 1
    if (password.match(/[~<>]+/)) strength += 1
    if (password.match(/[!@£$%^&()]+/)) strength += 1
    if (password.length > 5) strength += 1

    // Map strength to progress bar value
    let barValue = 0
    switch(strength) {
      case 0: barValue = 20; break
      case 1: barValue = 40; break
      case 2: barValue = 60; break
      case 3: barValue = 80; break
      case 4: barValue = 100; break
      default: barValue = 0
    }

    this.setState({ passwordStrength: barValue })
  }

  render() {
    const { auth } = this.props
    const { passwordStrength } = this.state

    return (
      <form onSubmit={this.submit}>
        <h1>Register</h1>
        <hr />
        <b>{auth.errorMessage && <span>{auth.errorMessage}</span>}</b>
        
        <div className="field is-horizontal">
          <div className="field-label is-normal">
            <label>Username</label>
          </div>
          <input 
            className="input is-medium"
            required 
            placeholder="User Name" 
            type="text" 
            name="user_name" 
            onChange={this.updateDetails}
          />
        </div>

        <div className="field is-horizontal">
          <div className="field-label is-normal">
            <label>Contact Number</label>
          </div>
          <input 
            className="input is-medium"
            required 
            placeholder="Contact Number" 
            type="text" 
            name="contact_number" 
            onChange={this.updateDetails}
          />
        </div>

        <div className="field is-horizontal">
          <div className="field-label is-normal">
            <label>Email Address</label>
          </div>
          <div className="field-body">
            <div className="field">
              <input 
                className="input is-medium"
                required 
                placeholder="Email Address" 
                type="text" 
                name="email_address" 
                onChange={this.updateDetails}
              />
            </div>
          </div>
        </div>

        <div className="field is-horizontal">
          <div className="field is-horizontal">
            <label>Password</label>
            {/* Bind progress bar value to our state */}
            <progress max="100" value={passwordStrength} id="strength"></progress>
          </div>
          <input 
            className="input is-medium"
            required 
            placeholder="Password" 
            type="password" 
            name="password" 
            onChange={this.updateDetails}
            {/* No need for ID now since we're using React state */}
          />
        </div>

        <div className="field is-horizontal">
          <div className="field is-horizontal">
            <label>Confirm Password</label>
          </div>
          <input 
            className="input is-medium"
            required 
            placeholder="Confirm Password" 
            type="password" 
            name="confirm_password" 
            onChange={this.updateDetails}
          />
        </div>

        <input className="button is-primary" value="Register" type="submit" />
      </form>
    )
  }
}

const mapStateToProps = ({ auth }) => ({ auth })
export default connect(mapStateToProps)(Register)

What Changed?

  1. Added passwordStrength to state: This tracks the progress bar value reactively.
  2. Moved strength calculation to a class method: checkPasswordStrength is now a bound class method that updates state instead of manipulating the DOM directly.
  3. Trigger strength calculation on password change: In updateDetails, after updating the password state, we call our strength calculation method.
  4. Bound progress bar to state: The progress bar's value prop is now linked to passwordStrength from state, so React handles updating the DOM automatically.
  5. Removed direct DOM operations: No more getElementById or addEventListener—we're using React's built-in event handling and state management, which is the proper way to do things in React.

Extra Tips

  • You could add visual feedback to the progress bar (like color changes) based on the strength value by applying conditional classes.
  • Consider refining the strength criteria to match your exact needs (e.g., adding uppercase letter requirements).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:29:48