Как мне перебрать массив MongoDB с React JS для рендеринга таблицы? - PullRequest
0 голосов
/ 26 мая 2019

В моем приложении MERN я пытаюсь создать компонент панели администратора. Этот компонент покажет таблицу с пользовательской информацией. Информация извлекается из коллекции MongoDB и затем передается в таблицу.

В настоящее время я использую цикл for для итерации массива, но было бы гораздо лучше использовать вместо этого функцию .map Javascript.

Однако, когда я переключаю приведенный ниже код на функцию .map вместо цикла for, это не работает, поэтому для меня это не имеет смысла.

Когда я пытаюсь заменить цикл функцией map, кажется, что код пытается отобразить массив до того, как он будет определен. Массив определяется с помощью вызова обещания от редуктора Redux. Поэтому, прежде чем приложение установит массив в состояние, код вызывает функцию 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 может привести к тому, что в некоторых случаях таблица будет отображаться дважды или трижды.

1 Ответ

0 голосов
/ 26 мая 2019

Каково начальное состояние для props.users? Просто чтобы быть понятным, он должен быть инициализирован как пустой массив. Трудно сказать без ошибок.

Второе, что я хотел бы попробовать, - это убедиться, что ваш props.users является массивом, обернув его в Array.from (this.props.users).

Третье, что может помочь вашему коду выглядеть чище, это то, что вместо создания элементов и добавления к ним атрибутов после создания используется литералов шаблона . Так что вместо того, чтобы перебирать и создавать элементы, вы просто делаете это динамически.

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