如何使用 React JS 循环遍历 MongoDB 数组以呈现表?

Posted

技术标签:

【中文标题】如何使用 React JS 循环遍历 MongoDB 数组以呈现表?【英文标题】:How do I loop Through a MongoDB Array with React JS to Render a Table? 【发布时间】:2019-10-12 00:31:17 【问题描述】:

在我的 MERN 应用程序中,我正在尝试创建一个管理仪表板组件。该组件将显示一个包含用户信息的表格。信息从 MongoDB 集合中提取,然后呈现到表中。

目前,我正在使用 for 循环遍历数组,但使用 .map javascript 函数会更好。

但是,当我将以下代码切换到 .map 函数而不是 for 循环时,它不起作用,为什么会发生这种情况对我来说毫无意义。

当我尝试用 map 函数替换循环时,代码似乎在数组被定义之前尝试映射它。该数组是通过来自 Redux reducer 的 promise 调用来定义的。所以在App将数组设置为状态之前,代码调用map函数并中断。

当我使用 for 循环时,出于某种神奇的原因,它会等待我的数组被设置,然后我可以显示表格。

关于为什么在这种情况下我不能使用 .map 函数但 for 循环可以完美运行的任何想法?下面是我的代码。

import React,  Component  from "react"
import  connect  from "react-redux"
import ReactDOM from "react-dom"
import  Table, Button, Container  from "reactstrap"

class AdminProfile extends Component 
  constructor(props) 
    super(props)
    this.renderTable = this.renderTable.bind(this)
    this.renderTableBody = this.renderTableBody.bind(this)
  

  renderTableBody() 
    const body = document.getElementById("table-body")
    const length = this.props.users.length
    for (var i = 0; i < this.props.users.length; i++) 
      const row = document.createElement("tr")
      row.id = this.props.users[i].discord_id
      const col1 = document.createElement("td")
      col1.innerText = this.props.users[i].discord_id
      const col2 = document.createElement("td")
      col2.innerText = this.props.users[i].email
      const date = new Date(this.props.users[i].pay_date)
      date.setMonth(date.getMonth() + 1)
      const col3 = document.createElement("td")
      col3.innerText = date.toLocaleDateString()
      const col4 = document.createElement("td")
      col4.innerText = this.props.users[i].status
      const col5 = document.createElement("td")
      col5.setAttribute("name", "button-column")
      col5.style.display = "inline-block"

      const button1 = document.createElement("Button")
      const button2 = document.createElement("Button")
      const button3 = document.createElement("Button")
      //button1.style.alignSelf = "center"
      button1.setAttribute("class", "btn-icon btn-simple btn btn-info btn-sm")
      button2.setAttribute(
        "class",
        "btn-icon btn-simple btn btn-success btn-sm"
      )
      button3.setAttribute("class", "btn-icon btn-simple btn btn-danger btn-sm")
      const button1icon = document.createElement("i")
      const button2icon = document.createElement("i")
      const button3icon = document.createElement("i")
      button1icon.setAttribute("class", "fa fa-user")
      button1icon.setAttribute("color", "info")
      button1icon.setAttribute("size", "sm")
      button2icon.setAttribute("class", "fa fa-edit")
      button2icon.setAttribute("color", "success")
      button2icon.setAttribute("size", "sm")
      button3icon.setAttribute("class", "fa fa-times")
      button3icon.setAttribute("color", "danger")
      button3icon.setAttribute("size", "sm")
      button1.appendChild(button1icon)
      button2.appendChild(button2icon)
      button3.appendChild(button3icon)

      col5.appendChild(button1)
      col5.appendChild(button2)
      col5.appendChild(button3)
      row.appendChild(col1)
      row.appendChild(col2)
      row.appendChild(col3)
      row.appendChild(col4)
      row.appendChild(col5)
      body.appendChild(row)
      if (length === i) 
        break
      
    
    // this.renderButtons()
  
  // renderButtons() 
  //   const rows = document.getElementsByName("button-column")
  //   for (var i = 0; i < rows.length; i++) 
  //     ReactDOM.render(
  //       <Container>
  //         <Button className="btn-icon btn-simple" color="info" size="sm">
  //           <i className="fa fa-user" />
  //         </Button>
  //         <Button className="btn-icon btn-simple" color="success" size="sm">
  //           <i className="fa fa-edit" />
  //         </Button>
  //         <Button className="btn-icon btn-simple" color="danger" size="sm">
  //           <i className="fa fa-times" />
  //         </Button>
  //       </Container>,
  //       document.querySelector(rows[i].name)
  //     )
  //   
  // 
  renderTable() 
    console.log(this.props.users)
    return (
      <Table responsive>
        <thead>
          <tr>
            <th className="text-left">ID</th>
            <th>Email</th>
            <th>Next Payment</th>
            <th className="text-left">Status</th>
            <th className="text-left">Actions</th>
          </tr>
        </thead>
        <tbody id="table-body">this.renderTableBody()</tbody>
      </Table>
    )
  
  render() 
    return (
      <div>
        <h1 style= textAlign: "center" >WELCOME ADMIN!</h1>
        <h4 style= textAlign: "center"  S>
          Users
        </h4>
        this.renderTable()
      </div>
    )
  


function mapStateToProps(state) 
  return 
    auth: state.auth,
    card: state.card,
    stock: state.stock,
    users: state.users
  


export default connect(mapStateToProps)(AdminProfile)

我想要的结果是代码更简洁,错误更少。在某些情况下,for 循环会导致表格被渲染两次或三次。

【问题讨论】:

任何帮助表示赞赏!非常感谢 使用 .map() 时遇到的错误是什么。你在 reducer 中为 state.users 设置的初始状态是什么? 【参考方案1】:

props.users 的初始状态是什么?为了清楚起见,它应该被初始化为一个空数组。很难说没有错误。

我要尝试的第二件事是通过将其包装在 Array.from(this.props.users) 中来确保您的 props.users 是一个数组。

第三件事可能有助于您的代码看起来更干净,而不是创建元素并在创建后向它们添加属性是使用template literals。因此,与其循环并创建元素,不如动态地进行。

Array.from(this.props.users).map(user => 
   return (
      `<tr key=$user.id id=$user.id>
        <td>$user.name</td> // or whatever info your trying to display 
      </tr>`
   )
)

【讨论】:

这无需我在 Redux 或后端做任何事情就可以工作。谢谢!救生员!

以上是关于如何使用 React JS 循环遍历 MongoDB 数组以呈现表?的主要内容,如果未能解决你的问题,请参考以下文章

React js循环遍历从刀片接收的数组

React Js循环遍历父数组以进行登录授权

循环遍历数组并一次显示单个项目,动态持续时间,如 react js 中的 setTimeout 或 SetInterval

循环遍历两个对象数组以将匹配值推送到新数组在 React 中不起作用,但在 JS Fiddle 中起作用

如何在 React JSX 中循环遍历数组中的某些项目 [重复]

如何使用 React.js 在 JSX 中循环对象