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
getElementByIdandaddEventListenerdirectly 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:
checkPasswordwas 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?
- Added
passwordStrengthto state: This tracks the progress bar value reactively. - Moved strength calculation to a class method:
checkPasswordStrengthis now a bound class method that updates state instead of manipulating the DOM directly. - Trigger strength calculation on password change: In
updateDetails, after updating the password state, we call our strength calculation method. - Bound progress bar to state: The progress bar's
valueprop is now linked topasswordStrengthfrom state, so React handles updating the DOM automatically. - Removed direct DOM operations: No more
getElementByIdoraddEventListener—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
相关产品推荐
相关产品推荐

