ReactJS перебирает массив состояний с динамическим ключом со своими данными
У меня есть массив, как:
"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() не является функцией.
Вот мой компонент реакции:
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 ответа
Ваш 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>
))}
Я считаю, что это происходит, потому что вы пытаетесь извлечь элементы из массива, который еще не имеет данных через 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 }