React评论应用中ReviewResponse组件编辑功能实现问题咨询
核心问题梳理
你的代码主要存在3个核心错误:
- 事件处理函数返回的JSX不会被React渲染,必须把渲染逻辑写到
render方法里通过状态判断 - 不应该把React组件存到state中,state仅用来存储状态标识(比如是否打开编辑表单的布尔值)
- 现有组件缺少编辑态的回填逻辑、更新回复的业务方法
分步修改代码
1. 修改ReviewResponseBox 组件
新增更新回复的方法,同时把该方法传给子组件:
import React from "react"; import ReviewResponse from "./ReviewResponse"; import ReviewResponseForm from "./ReviewResponseForm"; class ReviewResponseBox extends React.Component { state = { reviewResponses: JSON.parse(localStorage.getItem(`reviewResponses-${this.props.review_id}`)) || [] }; componentDidUpdate(prevProps, prevState) { if (prevState.reviewResponses !== this.state.reviewResponses) { localStorage.setItem( `reviewResponses-${this.props.review_id}`, JSON.stringify(this.state.reviewResponses) ); } } render() { const reviewResponses = this.getResponses(); const reviewResponseNodes = ( <div className="reviewResponse-list">{reviewResponses}</div> ); return ( <div className="reviewResponse-box"> {reviewResponses.length ? ( <>{reviewResponseNodes}</> ) : ( <ReviewResponseForm addResponse={this.addResponse.bind(this)} review_id={this.props.review_id} /> )} </div> ); } addResponse(review_id, author, body) { const reviewResponse = { review_id, author, body }; // 单条评论仅允许一个回复,直接赋值即可 this.setState({ reviewResponses: [reviewResponse] }); } // 新增更新回复的方法 updateResponse(review_id, author, body) { this.setState({ reviewResponses: [{review_id, author, body}] }) } getResponses() { return this.state.reviewResponses.map((reviewResponse) => { return ( <ReviewResponse author={reviewResponse.author} body={reviewResponse.body} review_id={this.props.review_id} // 把更新方法传给子组件 updateResponse={this.updateResponse.bind(this)} /> ); }); } } export default ReviewResponseBox;
2. 修改ReviewResponseForm 组件
支持接收初始值,兼容新增和编辑两种场景:
import React from "react"; class ReviewResponseForm extends React.Component { // 回填编辑态的初始值 componentDidMount() { if (this.props.isEdit) { this.author.value = this.props.initialAuthor this.body.value = this.props.initialBody } } render() { return ( <form className="response-form" onSubmit={this.handleSubmit.bind(this)}> <div className="response-form-fields"> <input placeholder="Name" required ref={(input) => this.author = input}></input><br /> <textarea placeholder="Response" rows="4" required ref={(textarea) => this.body = textarea}></textarea> </div> <div className="response-form-actions"> <button type="submit">{this.props.isEdit ? '保存修改' : '发布回复'}</button> {/* 编辑态加取消按钮 */} {this.props.isEdit && <button type="button" onClick={this.props.onCancel}>取消</button>} </div> </form> ); } handleSubmit(event) { event.preventDefault(); const author = this.author.value; const body = this.body.value; // 根据场景调用对应方法 if (this.props.isEdit) { this.props.updateResponse(this.props.review_id, author, body) this.props.onCancel() } else { this.props.addResponse(this.props.review_id, author, body); } } } export default ReviewResponseForm;
3. 修改ReviewResponse 组件
通过状态控制展示回复内容还是编辑表单,同时把原来的class属性替换为React标准的className避免警告:
import React from 'react'; import './ReviewResponse.css'; import ReviewResponseForm from "./ReviewResponseForm"; class ReviewResponse extends React.Component { state = { formOpen: false }; handleEditClick = () => { this.setState({formOpen: true}) } handleCancel = () => { this.setState({formOpen: false}) } render () { // 编辑态展示表单,否则展示回复内容 if (this.state.formOpen) { return <ReviewResponseForm isEdit initialAuthor={this.props.author} initialBody={this.props.body} review_id={this.props.review_id} updateResponse={this.props.updateResponse} onCancel={this.handleCancel} /> } return( <div className="response"> <span className="ellipsis"> <i className="ellipsis horizontal icon" onClick={this.handleEditClick} style={{ color: 'blue' }}></i> </span> <br></br> <span className="reply-icon"> <i className="reply icon" style={{ color: 'blue'}}></i> </span> <span className="response-content"> <p className="response-body">{this.props.body}</p> <p className="response-author"> {this.props.author}</p> <p className="response-date">{new Date().toISOString().split("T")[0].replaceAll("-", "/")}</p> <div className="response-footer"></div> </span> </div> ); } } export default ReviewResponse;
内容的提问来源于stack exchange,提问作者user16644688
相关产品推荐
相关产品推荐

