reactjs 如何正确显示用户在react中随机点击时的div内容

oymdgrw7  于 2023-02-18  发布在  React
关注(0)|答案(2)|浏览(168)

连续单击“用户”按钮时,以下代码成功地在页面底部显示用户div消息**(例如User1、User2、User3等)**

**这是我的问题:当我随机单击“用户”按钮时(例如,用户1、用户6、用户5、用户12等)**Div消息框散布在整个页面上,如下面的屏幕截图所示。

我不知道这个问题是来自css还是react组件。
请问我如何让每个用户的消息DIV正确显示在底部,无论用户按钮被点击连续或随机

<!DOCTYPE html>
<html>
   <head>

   </head>
   <body>
<script src="build/react.min.js"></script>
<script src="build/react-dom.min.js"></script>
<script src="build/browser.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">

<style>
.mainArea {
  position: fixed;
  width: 80%;
  bottom: 0%
}
.contact_box {
  position: relative;
  bottom: -5px;
  width: 250px;
  background: black;
  color: red;
  border-radius: 5px 5px 0px 0px;
  bottom: 0px;
  display: inline-block; 
}
</style>
<div id="app"></div>
<script type="text/babel">

class Application extends React.Component {
  constructor(props) {
    super(props);
this.state = {
      arr: [
    { id: 1,     name: "user1"},
    { id: 2,     name: "user2"},
    { id: 3,     name: "user3"},
    { id: 4,     name: "user4"},
    { id: 5,     name: "user5"},
    { id: 6,     name: "user6"},
    { id: 7,     name: "user7"},
    { id: 8,     name: "user8"},
    { id: 9,     name: "user9"},
    { id: 10,    name: "user10"},
    { id: 11,    name: "user11"},
    { id: 12,    name: "user12"},
    { id: 13,    name: "user13"},
    { id: 14,    name: "user14"},
    { id: 15,    name: "user15"}
      ],
popStatus: false,

    };
   this.popIt = this.popIt.bind(this);
  }

  popIt(id) {
   
this.state.arr[id].popStatus = true;
this.setState({
          popStatus: true
        });
     }

  render() {
    return (
        <div>
          <h3>List of users Records</h3>
<div class="sidebar">
          <ul>
            {this.state.arr.map((obj, i) => (
              <li key={i}>
                {obj.name} - {obj.name}
 <button
                  type="button"
                  onClick={() => { this.popIt(i); }}
                  className=""
                >
                 {obj.name}
                </button>
              </li>
            ))}
          </ul>
      </div>
<div className="mainArea">
            {this.state.arr.map((obj, i) => (
              <div  key={i} className="contact_box" >
{obj.popStatus === true && <div className="">
        <b>Username:</b> {obj.name}<br />
          Message .........<br />
          Message .........<br />
          Message .........<br />
          Message .........<br />
          Message .........<br />
          Message .........<br />
</div> 
   } 
</div> 
 ))}
</div>
</div>
    );
  }
}
ReactDOM.render(<Application />, document.getElementById('app'));
</script>
   </body>
</html>
oyjwcjzk

oyjwcjzk1#

您的问题部分是CSS的结果,部分是JSX中的条件呈现逻辑的结果。

CSS

您有一个样式化的 Package 器,无论popStatus是否为true,它都会为每个用户显示。该样式化的 Package 器具有固定的宽度,因此无论是否有任何内容实际呈现在其中,它都会占用页面上的空间。
更具体地说,您要为每个用户呈现这个div:

<div  key={i} className="contact_box" >

看看这行代码在JSX中的位置。
你在用户信息框中看到的列间距是div。你可以使用任何你想要的CSS,只要记住,如果你在你的呈现中包含一个元素来 Package 你对popStatus的条件检查,那么它将为每个用户显示。
最直接的解决方案是在条件检查后将其移除或在渲染中向下移动。

条件渲染

Map用户时,可以对popStatus***first***执行条件检查。
这样,您将只在满足条件时呈现某些内容。
此外,最好将key设置为用户id,以唯一标识用户,而不是使用索引。
注意:您应该避免直接改变状态。这一行:应将this.state.arr[id].popStatus = true;移到setState中,并且在执行此更新时应返回一个新副本。
注意:目前还不清楚在你的状态中顶层对象上的popStatus prop在做什么,因为它似乎与你的问题无关。我在演示中注解掉了它。
下面的演示应该会让你朝着正确的方向前进。

示例/演示(通过下面的链接查看)

https://codesandbox.io/s/user-list-pop-example-vuyx59

    • 样式. css**
.App {
  font-family: sans-serif;
  text-align: center;
}

.main-area {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
}

.contact-box {
  background: black;
  color: red;
  border-radius: 5px 5px 0px 0px;
  padding: 10px;
}
    • 应用程序js**
import "./styles.css";
import { useState } from "react";

const initialState = {
  users: [
    { id: 1, name: "user1", popStatus: false },
    { id: 2, name: "user2", popStatus: false },
    { id: 3, name: "user3", popStatus: false },
    { id: 4, name: "user4", popStatus: false },
    { id: 5, name: "user5", popStatus: false },
    { id: 6, name: "user6", popStatus: false },
    { id: 7, name: "user7", popStatus: false },
    { id: 8, name: "user8", popStatus: false },
    { id: 9, name: "user9", popStatus: false },
    { id: 10, name: "user10", popStatus: false },
    { id: 11, name: "user11", popStatus: false },
    { id: 12, name: "user12", popStatus: false },
    { id: 13, name: "user13", popStatus: false },
    { id: 14, name: "user14", popStatus: false },
    { id: 15, name: "user15", popStatus: false }
  ]
  // what was this for?
  // popStatus: false
};

export default function App() {
  const [state, setState] = useState(initialState);

  function popIt(id) {
    setState((prev) => {
      return {
        ...prev,
        users: prev.users.map((user) =>
          user.id === id ? { ...user, popStatus: true } : user
        )
      };
    });
  }
  return (
    <div className="App">
      <h3>List of users Records</h3>
      <ul style={{ listStyle: "none" }}>
        {state.users.map((user) => (
          <li key={user.id}>
            {user.name}{" "}
            <button
              type="button"
              onClick={() => {
                popIt(user.id);
              }}
            >
              {user.name}
            </button>
          </li>
        ))}
      </ul>
      <div className="main-area">
        {state.users.map(
          (user) =>
            user.popStatus && (
              <div key={user.id} className="contact-box">
                <b>Username:</b>
                {user.name}
                <br />
                Message .........
                <br />
                Message .........
              </div>
            )
        )}
      </div>
    </div>
  );
}

无论单击用户的顺序如何,用户信息都将按顺序显示的屏幕快照:

jyztefdp

jyztefdp2#

您的Map功能存在问题:

{this.state.arr.map((obj, i) => (
    <div  key={i} className="contact_box" >
        {obj.popStatus === true && <div className="">
           <b>Username:</b> {obj.name}<br />

首先打印contact_box div,然后选中popStatus,并在此基础上打印内容,因为您为cotact_box设置了CSS,始终打印,所以会有这些空白点。
只需将contact_box div移到if语句中,就可以了:

{this.state.arr.map((obj, i) => (
   {obj.popStatus === true &&
       <div  key={i} className="contact_box" >
           <b>Username:</b> {obj.name}<br />
           // rest of the box
       </div>
   }
 )}

在这个过程中,您可以去掉这个额外的div。
此外,我建议使用功能组件和钩子,这样管理状态会更简单,并且建议用于较新的React版本。

相关问题