简体   繁体   English

在地图内有条件地渲染对象的一部分 onClick (REACT.js)

[英]Conditionally render part of object onClick inside a map (REACT.js)

I am trying to conditionally render part of an object (user comment) onClick of button.我正在尝试在单击按钮时有条件地呈现对象的一部分(用户评论)。

The objects are being pulled from a Firebase Database.正在从 Firebase 数据库中提取对象。

I have multiple objects and want to only render comments for the Result component I click on.我有多个对象,并且只想为我单击的 Result 组件呈现注释。

The user comment is stored in the same object as all the other information such as name, date and ratings.用户评论与所有其他信息(如姓名、日期和评级)存储在同一对象中。

My original approach was to set a boolean value of false to each Result component and try to change this value to false but cannot seem to get it working.我最初的方法是为每个 Result 组件设置一个布尔值 false 并尝试将此值更改为 false 但似乎无法使其正常工作。

Code and images attached below, any help would be greatly appreciated.下面附上代码和图片,任何帮助将不胜感激。

{
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 >
        )
    })

界面截图

You have to track individual state of each button toggle in that case.在这种情况下,您必须跟踪每个按钮切换的单独状态。

The solution I think of is not the best but you could create a click handler for the button and adding a classname for the span then check if that class exists.我想到的解决方案不是最好的,但您可以为按钮创建一个单击处理程序并为span添加一个类名,然后检查该类是否存在。 If it exists then, just hide the comment.如果它存在,则隐藏评论。 Just make sure that the next sibling of the button is the target you want to hide/show只需确保按钮的下一个兄弟是您要隐藏/显示的目标

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>

You can try like this:你可以这样试试:

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>

You can store an array with that place s which are clicked, for example:您可以存储一个包含被点击的place的数组,例如:

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));
   }
}

and in your render function并在您的渲染功能中

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 >
        )
    })

You need to use useState or your component won't update even if you change the property from false to true.您需要使用useState否则即使您将属性从 false 更改为 true,您的组件也不会更新。

In order to do so you need an id since you might have more than one post.为此,您需要一个 id,因为您可能有多个帖子。 (Actually you have a timestamp already, you can use that instead of an 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
    }
  ]);

Create a function that updates the single property and then updates the state.创建一个更新单个属性然后更新状态的函数。

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

Then you can conditionally render the comment.然后您可以有条件地呈现评论。

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>
    );

Check this codesandbox to see how it works.检查此 代码和框以了解其工作原理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM