ReactJS перебирает массив состояний с динамическим ключом со своими данными - PullRequest
0 голосов
/ 13 февраля 2019

У меня есть массив вроде:

"data": {
    "key1": {
        "key_val1": "data1",
        "key_val2": "data2",
        "key_val3": "data3",
        "key_val4": "data4",

    },
    "key2": {
        "key_val1": "data1",
        "key_val2": "data2",
        "key_val3": "data3",
        "key_val4": "data4",

    },
    "key3": {
        "key_val1": "data1",
        "key_val2": "data2",
        "key_val3": "data3",
        "key_val4": "data4",

    }
}

Я хочу перебрать этот массив и заполнить свою таблицу, но я получаю ошибку this.state.data.map () не являетсяfunction .

Вот мой компонент реакции:

import React, { Component } from "react";
import $ from "jquery";
import axios from "axios";

class DataComponent extends Component {
  state = {
    data: [],
    isLoading: true
  };
  componentDidMount() {
    this.getData();
  }

  getData() {
    var curr_date = new Date().toISOString().substring(0, 10);
    const params = new FormData();
    params.append("date", curr_date);
    axios
      .post(`http://api.mydomain.in/getdataList/`, params)
      .then(res => {
        if (res.data.result === 1) {
          this.setState({
            data: res.data.data,
            isLoading: false
          });
        }
        if (!this.state.isLoading) {
          this.initTable();
        }

      })
      .catch(err => {
        console.log(err);
      });
  }

  initTable() {
    $("#my_table").DataTable({
      bLengthChange: false,
      lengthMenu: [[15, 15, 15, "All"]],
      language: {
        search: "_INPUT_",
        searchPlaceholder: "Search records"
      }
    });
  }

  render() {
    return (
      <div className="tab-pane active" id="mytab">
        <div className="inner-content table-responsive">
          <table id="my_table" className="display" style={{ width: "100%" }}>
            <thead>
              <tr className="heading-table">
                <th>Col1</th>
                <th>col2 </th>
                <th>col3 </th>
                <th>col4 </th>
                <th>col5 </th>
              </tr>
            </thead>
            {this.state.isLoading ? null : (
              <tbody>
                {this.state.data.map(d => (
                  <tr>
                    <td>{d}</td>
                    <td>{d.key_val1}</td>
                    <td>{d.key_val2}</td>
                    <td>{d.key_val3}</td>
                    <td>{d.key_val4}</td>
                  </tr>
                ))}
              </tbody>
            )}
          </table>
        </div>
      </div>
    );
  }
}

export default DataComponent;

this.state.data будет обновлен образцом массива, как показано выше.

Как мне добитьсяэтот?Я тоже пробовал с Object.keys(this.state.data).map(), но не повезло.

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 13 февраля 2019

Ваша переменная data является объектом JSON, а не массивом.Чтобы преобразовать его в массив и получить ключи и значения, вы можете использовать Object.entries.

Эта функция вернет массив, содержащий другие массивы с ключом в качестве первого значения,и значение в качестве второго:

{Object.entries(this.state.data).map(([key, value]) => (
    <tr key={key}>
        <td>{key}</td>
        <td>{value.key_val1}</td>
        <td>{value.key_val2}</td>
        <td>{value.key_val3}</td>
        <td>{value.key_val4}</td>
    </tr>
))}

Если вам не нужны ключи вашего объекта, вы можете использовать Object.values.

Альтернатива с использованием деконструкции:

{Object.entries(this.state.data).map(([key, { key_val1, key_val2, key_val3, key_val4 }]) => (
    <tr key={key}>
        <td>{key}</td>
        <td>{key_val1}</td>
        <td>{key_val2}</td>
        <td>{key_val3}</td>
        <td>{key_val4}</td>
    </tr>
))}

Другая версия, использующая вложенное отображение, которая будет работать с любыми объектами:

{Object.entries(this.state.data).map(([key, value]) => (
    <tr key={key}>
        <td>{key}</td>
        {Object.entries(value).map(([name, data]) => <td key={name} >{data}</td>)}
    </tr>
))}
0 голосов
/ 13 февраля 2019

Я полагаю, что это происходит, потому что вы пытаетесь извлечь элементы из массива, в котором еще нет данных, через this.state.data.map() Во время первоначального рендеринга состояние вашего компонента еще не содержит никаких данных, а ваш getData() метод не запускается до ПОСЛЕ первоначального рендера.Вы можете выполнить быструю начальную проверку, чтобы увидеть, есть ли в вашем штате данные, прежде чем выполнить this.state.data.map, например,

{this.state.data ? this.state.data.map(d => (
        <tr>
            <td>{d}</td>
            <td>{d.key_val1}</td>
            <td>{d.key_val2}</td>
            <td>{d.key_val3}</td>
            <td>{d.key_val4}</td>
        </tr>
  )) : null }
...