React.js开发中Forms组件this.props为空的问题求助
问题原因
你的核心问题是React单向数据流的使用错误:
- 你把复选框的选中状态存在了子组件
CheckBox的内部state中,默认父组件Forms是无法直接访问子组件内部state的 - 你没有给
CheckBox组件传递任何自定义props,也没有给Forms组件传入value属性,所以Forms中打印的props为空、初始的submit状态为undefined都是正常现象 - 额外问题:当前
CheckBox内有2个复选框,但共用了同一个checkBoxChecked状态,两个复选框的选中逻辑会互相干扰,无法正确记录各自的选中状态
修复方案
采用状态提升的逻辑:把复选框的选中状态放到父组件Forms中管理,子组件通过props接收状态和修改状态的回调函数即可。
第一步:修改CheckBox组件代码
import React from "react"; class CheckBox extends React.Component { // 子组件不用自己维护状态,所有状态和修改逻辑都来自父组件传入的props handleCheckBoxClick = (e) => { const currentValue = e.target.value; const currentChecked = e.target.checked; const { checkedOptions, onChange } = this.props; let newCheckedOptions; if (currentChecked) { // 选中就加入数组 newCheckedOptions = [...checkedOptions, currentValue]; } else { // 取消选中就从数组移除 newCheckedOptions = checkedOptions.filter(item => item !== currentValue); } // 调用父组件传入的回调,把最新的选中结果传给父组件 onChange(newCheckedOptions); }; render() { const { checkedOptions } = this.props; return ( <div> <div className="form-check form-check-inline" style={{ paddingTop: "20px" }} > <input className="form-check-input" type="checkbox" id="inlineCheckbox1" value="option1" checked={checkedOptions.includes("option1")} onChange={this.handleCheckBoxClick} /> <label className="form-check-label" htmlFor="inlineCheckbox1"> Daily </label> </div> <div className="form-check form-check-inline"> <input className="form-check-input" type="checkbox" id="inlineCheckbox2" value="option2" checked={checkedOptions.includes("option2")} onChange={this.handleCheckBoxClick} /> <label className="form-check-label" htmlFor="inlineCheckbox2"> Hourly </label> </div> </div> ); } } export default CheckBox;
第二步:修改Forms组件代码
import React from "react"; import CheckBox from "../checkBox/checkBox"; import axios from "axios"; class Forms extends React.Component { constructor(props) { super(props); this.state = { emails: "", alerts: "", checkedOptions: [], // 存储复选框选中的内容 }; this.handleSubmit = this.handleSubmit.bind(this); } handleAlertButtonClick = () => { const data = this.state.alerts; axios.post("/test", data); console.log(data); }; handleSaveButtonClick = () => { const data = this.state.alerts; axios.post("/save", data); console.log(data); }; handleSaveChange = (e) => { this.setState({ alerts: e.target.value }); }; // 新增:接收子组件传过来的复选框选中结果,更新父组件state handleCheckBoxChange = (newCheckedOptions) => { this.setState({ checkedOptions: newCheckedOptions }); }; handleEmailChange = (e) => { this.setState({ emails: e.target.value }); }; handleSubmit = (event) => { event.preventDefault(); // 校验规则:至少选中一个复选框,告警信息和邮箱不为空 if (this.state.checkedOptions.length === 0 || !this.state.alerts || !this.state.emails) { alert("This form is invalid please try again!"); return; } alert("Your form has been succesfully submitted"); }; render() { return ( <div> <form className="needs-validation" onSubmit={this.handleSubmit}> <div className="form-group" style={{ paddingTop: "40px" }}> <label htmlFor="alertInput"> Alert Message</label> <input type="text" className="form-control" id="alertInput" placeholder="Alert Message" value={this.state.alerts} onChange={this.handleSaveChange} required /> </div> {/* 给CheckBox传入状态和回调props */} <CheckBox required checkedOptions={this.state.checkedOptions} onChange={this.handleCheckBoxChange} /> <div className="form-group" style={{ paddingTop: "30px" }}> <label htmlFor="emailInput">Email Recipients</label> <input type="email" multiple className="form-control" id="emailInput" placeholder="Email Recipients" value={this.state.emails} onChange={this.handleEmailChange} required /> </div> <div className="d-grid gap-2 d-md-flex justify-content-md-end" style={{ paddingTop: "25px" }} > <button className="btn btn-primary me-md-2" type="submit" onClick={this.handleAlertButtonClick} > Test Alert </button> <button className="btn btn-primary" type="submit" onClick={this.handleSaveButtonClick} > Save </button> </div> </form> </div> ); } } export default Forms;
核心逻辑说明
- 所有表单相关的状态都统一在父组件
Forms中管理,方便提交时统一校验和获取数据 - 子组件
CheckBox只负责渲染和交互,通过props接收父组件的状态和修改回调,没有内部冗余状态 - 复选框的选中结果存在数组中,可以同时支持单选、多选的校验需求
内容的提问来源于stack exchange,提问作者Alfred Eben-Foby
相关产品推荐
相关产品推荐

