组件中constructor无法获取Redux Store的props,但render函数可以
问题原因
组件的constructor在初始化阶段执行,此时Redux Store中的users数据可能还未加载完成(比如异步请求还没返回),因此this.props.users为null。而render方法会在组件接收到新props时重新执行,当users数据加载完成、Store更新后,this.props.users就会有有效值,所以你能在render中获取到。
解决方案
方案1:通过生命周期钩子同步state与props
利用componentDidMount(组件挂载后)和componentDidUpdate(props更新时)钩子,在users数据就绪后更新组件state:
import React, { Component } from "react"; import { connect } from "react-redux"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faFaceSmile, faFaceFrown } from "@fortawesome/free-solid-svg-icons"; import axios from "axios"; const mapStateToProps = (state) => { return { userId: state.userId, users: state.users, }; }; class EditProfile extends Component { constructor(props) { super(props); this.state = { name: "", email: "", gander: "", message: null, }; } // 组件挂载后初始化state componentDidMount() { this.syncUserState(); } // props更新时同步state(避免重复更新) componentDidUpdate(prevProps) { if (prevProps.users !== this.props.users || prevProps.userId !== this.props.userId) { this.syncUserState(); } } // 提取公共方法同步用户数据到state syncUserState() { const { users, userId } = this.props; if (users) { const currentUser = users.find(item => item.userId === userId); if (currentUser) { this.setState({ name: currentUser.name, email: currentUser.email, gander: currentUser.gander, }); } } } render() { const { users, userId } = this.props; const currentUser = users?.find(item => item.userId === userId); return ( <div className="col"> <h4 className="h4 my-2"> {currentUser?.name || ""}'s Info </h4> {/* 这里可以使用this.state中的值渲染表单控件 */} </div> ); } } export default connect(mapStateToProps)(EditProfile);
方案2:直接使用props,避免冗余state
如果你的表单是受控组件,可以直接在onChange时更新state,初始值在componentDidMount中设置:
class EditProfile extends Component { constructor(props) { super(props); this.state = { name: "", email: "", gander: "", message: null, }; } componentDidMount() { const { users, userId } = this.props; if (users) { const currentUser = users.find(item => item.userId === userId); if (currentUser) { this.setState({ name: currentUser.name, email: currentUser.email, gander: currentUser.gander, }); } } } // 表单输入变化时更新state handleInputChange = (e) => { this.setState({ [e.target.name]: e.target.value }); } render() { const { users, userId } = this.props; const currentUser = users?.find(item => item.userId === userId); return ( <div className="col"> <h4 className="h4 my-2"> {currentUser?.name || ""}'s Info </h4> <form> <div className="mb-3"> <label className="form-label">Name</label> <input type="text" name="name" className="form-control" value={this.state.name} onChange={this.handleInputChange} /> </div> <div className="mb-3"> <label className="form-label">Email</label> <input type="email" name="email" className="form-control" value={this.state.email} onChange={this.handleInputChange} /> </div> {/* 性别输入框类似 */} </form> </div> ); } }
额外优化:可选链操作符简化代码
使用ES6+的可选链操作符?.可以避免大量的null/undefined判断,比如users?.find(...)和currentUser?.name,让代码更简洁。
内容的提问来源于stack exchange,提问作者Ferdous Hasan
相关产品推荐
相关产品推荐

