React+Node+MySQL登录后Profile页TypeError问题求助
Let's break down the issues causing this error and fix them step by step:
1. Critical State Initialization Bug in Profile.js
The biggest issue is in your Profile component's constructor: you're overwriting the setState method instead of initializing the component's state. This breaks your component's state management entirely.
Wrong Code:
constructor() { super() console.log('profile class') this.setState = { first_name: '', last_name: '', email: '' } }
Fixed Code:
constructor() { super() console.log('profile class') // Initialize state correctly (don't overwrite setState!) this.state = { first_name: '', last_name: '', email: '' } }
2. Missing Token Validation & Error Handling in Profile.js
Even if the token exists, decoding it can fail (e.g., invalid token, expired token). You need to add checks to avoid trying to access properties on null or undefined.
Updated componentDidMount:
componentDidMount() { const token = localStorage.getItem('usertoken') // Redirect to login if no token exists if (!token) { this.props.history.push('/login') return } try { const decoded = jwt_decode(token) console.log('Decoded token data:', decoded) // Use object logging for clarity this.setState({ first_name: decoded.first_name, last_name: decoded.last_name, email: decoded.email }) } catch (err) { console.error('Token decoding failed:', err) // Redirect on invalid token this.props.history.push('/login') } }
3. Input Value Stored as Array in Login.js
Your onChange handler in Login is wrapping input values in arrays, which can cause unexpected issues with backend validation (even if it didn't break login here).
Wrong Code:
onChange(e){ this.setState({[e.target.name]: [e.target.value]}) }
Fixed Code:
onChange(e){ this.setState({[e.target.name]: e.target.value}) }
4. Optional: Improve Error Handling in Login Flow
Add error handling to your login function and component to catch failed attempts gracefully:
Updated UserFunctions.js login Function:
export const login = user => { return axios .post('/users/login', { email: user.email, password: user.password }) .then(res=>{ localStorage.setItem('usertoken', res.data) return res.data }) .catch(err => { console.log(err) // Re-throw error so frontend can handle it throw err }) }
Updated Login.js onSubmit:
onSubmit(e){ e.preventDefault() const user = { email: this.state.email, password: this.state.password } login(user).then(res=> { this.props.history.push(`/profile`) }).catch(err => { alert(`Login failed: ${err.response?.data?.error || 'Unknown error'}`) }) }
5. Verify Token Payload (Optional)
To confirm your token contains the expected data, add a log in your backend login route before signing the token:
console.log('User data to encode:', user.dataValues); let token = jwt.sign(user.dataValues, process.env.SECRET_KEY, { expiresIn: 1440 })
This will let you check if first_name, last_name, and email are present in the data being signed into the token.
These fixes should resolve the "Cannot read property 'first_name' of null" error and improve the robustness of your auth flow.
内容的提问来源于stack exchange,提问作者Jawad Ali

