【问题标题】:Conditional rendering in React based on current component stateReact 中基于当前组件状态的条件渲染
【发布时间】:2021-10-22 04:19:17
【问题描述】:

我正在努力弄清楚如何在 React 中实现条件渲染。基本上,我想做的是:如果reviewResponses 数组中有reviewResponse,我不再想渲染reviewResponseForm。我只想渲染那个 ReviewResponse。换句话说,每条评论在这个应用程序中只能有一个回复。 我不确定在尝试实现这个逻辑时我做错了什么。我知道我需要实现某种条件语句,如果我的 reviewResponses 数组的长度大于 0,我需要呈现表单。否则,我需要渲染那个 reviwResponse。我写的每一条语句在这里都不起作用。有人有建议吗? 到目前为止,这是我的代码:

我的 review cardDetails 组件渲染了我的 ReviewResponseBox 组件,并将特定的 reviewId 作为 props 传递:

import React from "react";
import { useLocation } from "react-router-dom";
import StarRatings from "react-star-ratings";
import ReviewResponseBox from "../ReviewResponse/ReviewResponseBox";

const ReviewCardDetails = () => {
  const location = useLocation();
  const { review } = location?.state; // ? - optional chaining

  console.log("history location details: ", location);
  return (
    <div key={review.id} className="card-deck">
      <div className="card">
        <div>
          <h4 className="card-title">{review.place}</h4>
          <StarRatings
            rating={review.rating}
            starRatedColor="gold"
            starDimension="20px"
          />
          <div className="card-body">{review.content}</div>
          <div className="card-footer">
            {review.author} - {review.published_at}
          </div>
        </div>
      </div>
      <br></br>
       {/*add in conditional logic to render form if there is not a response and response if there is one*/} 
    <ReviewResponseBox review_id={review.id}/>

    </div>
  );
};

export default ReviewCardDetails;

然后,最终我希望这个组件 ReviewResponseBox 来确定是呈现响应表单还是呈现reviewresponse本身(如果它已经存在的话)。

import React from 'react';
import ReviewResponse from './ReviewResponse';
import ReviewResponseForm from './ReviewResponseForm';

class ReviewResponseBox extends React.Component {
  constructor() {
    super()

    this.state = {
      reviewResponses: []
    };
  }
  
  render () {
    const reviewResponses = this.getResponses();
    const reviewResponseNodes = <div className="reviewResponse-list">{reviewResponses}</div>;
   

    return(
      <div className="reviewResponse-box">
        <ReviewResponseForm addResponse={this.addResponse.bind(this)}/>
       
        <h3>Response</h3>
        {reviewResponseNodes}
        
      </div>  
        
    );
  } 
  

  addResponse(review_id, author, body) {
    const reviewResponse = {
      review_id,
      author,
      body
    };
    this.setState({ reviewResponses: this.state.reviewResponses.concat([reviewResponse]) }); // *new array references help React stay fast, so concat works better than push here.
  }
   
  
  
  getResponses() {    
    return this.state.reviewResponses.map((reviewResponse) => { 
      return (
        <ReviewResponse 
          author={reviewResponse.author} 
          body={reviewResponse.body} 
          review_id={this.state.review_id} />
      ); 
    });
  }

  
  
}
export default ReviewResponseBox;

这里是 ReviewResponseForm 和 ReviewResponse 组件:

import React from "react";

class ReviewResponseForm extends React.Component {
  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">Post Response</button>
        </div>
      </form>
    );
  }
  
  handleSubmit(event) { 
    event.preventDefault();   // prevents page from reloading on submit
    let review_id = this.review_id
    let author = this.author;
    let body = this.body;
    this.props.addResponse(review_id, author.value, body.value);
  }
} 

export default ReviewResponseForm;
import React from 'react';

class ReviewResponse extends React.Component {
    render () {
      return(
        <div className="response">
          <p className="response-header">{this.props.author}</p>
          <p className="response-body">- {this.props.body}</p>
          <div className="response-footer">
            </div>
        </div>
      );
    }
  
  }
  export default ReviewResponse;
  

任何建议都会有所帮助,谢谢。

【问题讨论】:

  • 你试过{reviewResponseNodes.length !=0 &amp;&amp; reviewResponseNodes}
  • 你建议我把代码放在哪里?

标签: javascript reactjs react-props react-state conditional-rendering


【解决方案1】:

如果我正确理解您的问题,如果this.state.reviewResponses 状态数组为空,您想呈现ReviewResponseForm

使用真(非零)/假(零)数组长度属性有条件地呈现任一 UI 元素。

render () {
  const reviewResponses = this.getResponses();
  const reviewResponseNodes = <div className="reviewResponse-list">{reviewResponses}</div>;


  return(
    <div className="reviewResponse-box">
      {reviewResponses.length 
        ? (
          <>
            <h3>Response</h3>
            {reviewResponseNodes}
          </>
        )
        : (
          <ReviewResponseForm addResponse={this.addResponse.bind(this)}/>
        )}
    </div>  
    
  );
} 

【讨论】:

  • 太好了,很有效-谢谢!但是当我刷新页面时,我的评论回复消失了,表单再次显示出来。知道为什么响应没有留下来吗?新的反应和一般的编码......如果你有时间,任何见解都会有所帮助。非常感谢
  • @bab React 状态是短暂的并且存在于内存中,每次ReviewResponseBox 挂载(如重新加载页面和应用程序时)reviewResponses 状态最初设置为[]。您需要将状态更改持久化到长期存储,即更新时的 localStorage,以及当组件挂载时,从 localStorage 读取并设置/初始化状态。
猜你喜欢
  • 2019-07-11
  • 2018-12-21
  • 2017-02-03
  • 1970-01-01
  • 2020-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-26
相关资源
最近更新 更多