【问题标题】:Conditionally render part of object onClick inside a map (REACT.js)在地图内有条件地渲染部分对象 onClick (REACT.js)
【发布时间】:2021-02-05 06:34:45
【问题描述】:

我正在尝试在单击按钮时有条件地呈现对象的一部分(用户评论)。

正在从 Firebase 数据库中提取对象。

我有多个对象,只想为我单击的 Result 组件呈现 cmets。

用户评论与姓名、日期和评分等所有其他信息存储在同一个对象中。

我最初的方法是为每个 Result 组件设置一个布尔值 false 并尝试将此值更改为 false,但似乎无法使其正常工作。

下面附上代码和图片,任何帮助将不胜感激。

{
accumRating: 3.7
adheranceRating: 4
cleanRating: 2
date: "2020-10-10"
place: "PYGMALIAN"
staffRating: 5
timestamp: t {seconds: 1603315308, nanoseconds: 772000000}
userComment: "Bad"
viewComment: false
}
    const results = props.data.map((item, index) => {
        return (
            <div className='Results' key={index}>
                <span>{item.place}</span>
                <span>{item.date}</span>
                <Rating
                    name={'read-only'}
                    value={item.accumRating}
                    style={{
                        width: 'auto',
                        alignItems: 'center',
                    }}
                />

                <button>i</button>
                {/* <span>{item.userComment}</span> */}

            </div >
        )
    })

【问题讨论】:

  • 您是否尝试过使用短路运算符? {item.viewComment &amp;&amp; &lt;span&gt;{item.userComment}&lt;/span&gt;}
  • 您希望切换按钮显示 cmets 吗? viewComment 来自 firebase 还是您手动设置?
  • @Rohitha 是的,基本上我想要一个切换按钮来查看更多信息(cmets)并在名称、日期和评级下方显示 cmets。 viewComment 来自 Firebase。也许我应该改变这个?
  • 不,可以根据viewComment设置状态并渲染。
  • 检查一下,我创建了一个小演示。 codesandbox.io/s/tender-bell-nsgsw

标签: javascript reactjs ecmascript-6 frontend


【解决方案1】:

您需要使用useState,否则即使您将属性从 false 更改为 true,您的组件也不会更新。

为此,您需要一个 ID,因为您可能有多个帖子。 (其实你已经有了时间戳,你可以用它来代替id。)

const [posts, setPosts] = useState([
    {
      id: 1,
      accumRating: 3.7,
      adheranceRating: 4,
      cleanRating: 2,
      date: "2020-10-10",
      place: "PYGMALIAN",
      staffRating: 5,
      timestamp: { seconds: 1603315308, nanoseconds: 772000000 },
      userComment: "Bad",
      viewComment: false
    }
  ]);

创建一个更新单个属性然后更新状态的函数。

const handleClick = (id) => {
    const singlePost = posts.findIndex((post) => post.id === id);
    const newPosts = [...posts];
    newPosts[singlePost] = {
      ...newPosts[singlePost],
      viewComment: !newPosts[singlePost].viewComment
    };
    setPosts(newPosts);
  };

然后你可以有条件地渲染评论。

return (
      <div className="Results" key={index}>
        <span>{item.place}</span>
        <span>{item.date}</span>
        <Rating
          name={"read-only"}
          value={item.accumRating}
          style={{
            width: "auto",
            alignItems: "center"
          }}
        />

        <button onClick={() => handleClick(item.id)}>i</button>
        {item.viewComment && <span>{item.userComment}</span>}
      </div>
    );

查看此codesandbox 以了解其工作原理。

【讨论】:

    【解决方案2】:

    您可以使用被点击的places 存储一个数组,例如:

    const [ selectedItems, setSelectedItems] = React.useState([]);
    
    const onClick = (el) => {
       if (selectedItems.includes(el.place)) {
         setSelectedItems(selectedItems.filter(e => e.place !== el.place));
       } else {
         setSelectedItems(selectedItems.concat(el));
       }
    }
    

    在你的渲染函数中

    const results = props.data.map((item, index) => {
            return (
                <div className='Results' key={index}>
                    <span>{item.place}</span>
                    <span>{item.date}</span>
                    <Rating
                        name={'read-only'}
                        value={item.accumRating}
                        style={{
                            width: 'auto',
                            alignItems: 'center',
                        }}
                    />
    
                    <button onClick={() => onClick(item)}>i</button>
    { /* HERE */ }
                    { selectedItems.includes(item.place) && <span>{item.userComment}</span> }
    
                </div >
            )
        })
    

    【讨论】:

      【解决方案3】:

      你可以这样试试:

      const [backendData, setBackendData] = useState([]);
      
      ...
      
      const showCommentsHandler = (viewComment, index) => {
            let clonedBackendData = [...this.state.backendData];
            clonedBackendData[index].viewComment = !viewComment;
      
            setBackendData(clonedBackendData);
      
          }
      
      ....
      return(
         <div>
          ....
          <button onClick={() => showCommentsHandler(item.viewComment, index)}>i</button>
          {item.viewComment && item.userComment}
        <div>
      

      【讨论】:

      • 我应该将前两部分放在我的 app.js 文件中吗?或 Results.js 中的所有内容
      • 希望您在 Results.js 中从 firebase 获取数据。如果不是,则应将前两部分放在要获取的组件中,然后在 props 中传递 showCommentsHandler。
      【解决方案4】:

      在这种情况下,您必须跟踪每个按钮切换的单独状态。

      我认为的解决方案不是最好的,但您可以为按钮创建一个单击处理程序并为span 添加一个类名,然后检查该类是否存在。如果它存在那么,只需隐藏评论。 只需确保按钮的下一个兄弟是您要隐藏/显示的目标

      const toggleComment = (e) => {
        const sibling =  e.target.nextElementSibling;
        sibling.classList.toggle('is-visible');
        
        if (sibling.classList.contains('is-visible')) {
          sibling.style.display = 'none'; // or set visibility to hidden
        } else {
          sibling.style.display = 'inline-block'; // or set visibility to visible
        }
      }
      
      <button onClick={toggleComment}>i</button>
      <span>{item.userComment}</span>
      

      【讨论】:

        猜你喜欢
        • 2022-07-30
        • 2021-06-30
        • 2019-03-24
        • 2015-05-16
        • 1970-01-01
        • 2013-10-11
        • 2022-07-23
        • 2021-10-23
        • 2023-03-22
        相关资源
        最近更新 更多