React 中基于当前组件状态的条件渲染

Posted

技术标签:

【中文标题】React 中基于当前组件状态的条件渲染【英文标题】:Conditional rendering in React based on current component state 【发布时间】: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 你建议我把代码放在哪里? 【参考方案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 读取并设置/初始化状态。

以上是关于React 中基于当前组件状态的条件渲染的主要内容,如果未能解决你的问题,请参考以下文章

react redux 公共状态管理---数据的渲染,数据的修改,再把修改的数据渲染到当前组件

基于用户输入的条件渲染

React Router VS 条件渲染

react 全家桶条件渲染

React 中的条件渲染不起作用,状态不能正常工作?

渲染的钩子比预期的要少。这可能是由于意外提前退货声明造成的。基于状态的条件渲染组件