РЕАКТИРОВАТЬ: преобразовать вложенный массив объектов в линейную форму
Я получаю данные из API с помощью Axios и сохраняю их в переменной состояния реакции.
Затем в моем методе рендеринга я пытаюсь деструктурировать полученные данные (которые представляют собой вложенный массив объектов) в линейную форму и использовать их в моей таблице реакций.
это структура извлеченных данных:
[
{ "uuid": "c47dea20",
"siteName": "dfsf",
"systemName": "bl",
"measurementName": ",nk",
"statistics": {
"dateStart": "2020-04-20T00:00:00Z",
"dateStop": "2020-04-21T00:00:00Z",
"values": [
"temperature1",
"temperature2"
],
"min": [1, 2],
"max": [10, 11],
"average": [5, 6],
"last": [7, 8],
"bucket_size": "4h",
"buckets": {
"term": "count",
"values": [5,4,4,5,6,6]
}
}
}
]
Вот как я пытаюсь разрушить:
// gives error: TypeError: Cannot read property 'buckets' of undefined
const {
measurementsData: {
statistics: {
buckets: [{ values: bucketValues }],
},
},
} = this.state;
console.log(bucketValues);
Ниже приведен полный код моего компонента:
class Table extends Component {
constructor(props) {
super(props);
this.state = {
measurementsData: [],
isLoading: false,
dropdownOpen: false,
};
}
signal = axios.CancelToken.source();
componentDidMount() {
this.handleGetmeasurementsDataInfo();
this.addFilterPlaceholder();
}
componentWillUnmount() {
this.signal.cancel("Api is being canceled");
// fix Warning: Can't perform a React state update on an unmounted component
this.setState = (state, callback) => {
return;
};
}
handleGetmeasurementsDataInfo = async () => {
this.setState({ isLoading: true });
await axios
.get("https://run.mocky.io/v3/d2f89c5b-487f-409c-bf2c-705b7d91e12d")
.then((response) => {
// handle success
console.log("measurement data:", response.data);
this.setState({ measurementsData: response.data });
})
.catch((error) => {
// handle error
if (axios.isCancel(error)) {
console.log("Unable to fetch measurementsData", error.message);
} else {
this.setState({ isLoading: false });
}
});
};
addFilterPlaceholder = () => {
const filters = document.querySelectorAll("div.rt-th > input");
for (let filter of filters) {
filter.placeholder = "Search..";
}
};
toggleDropdown = () => {
this.setState((state) => {
return {
dropdownOpen: !state.dropdownOpen,
};
});
};
render() {
const { dropdownOpen, measurementsData } = this.state;
// gives error: TypeError: Cannot read property 'buckets' of undefined
const {
measurementsData: {
statistics: {
buckets: [{ values: bucketValues }],
},
},
} = this.state;
console.log(bucketValues);
return (
<>
<div className="content">
<Row className="mt-5">
<Col xs={12} md={12}>
<Card>
<CardHeader>
<CardTitle tag="h4">heading</CardTitle>
<hr />
<Dropdown isOpen={dropdownOpen} toggle={this.toggleDropdown}>
<DropdownToggle caret>Ships</DropdownToggle>
{measurementsData.map((measurementData) => {
return (
<DropdownMenu key={measurementData.siteName}>
<DropdownItem>
{measurementData.siteName}
<DropdownItem divider />
</DropdownItem>
</DropdownMenu>
);
})}
</Dropdown>
</CardHeader>
<CardBody>
<p>static data </p>
<Line data={chartExample9.data} />
<p>dynamic data </p>
<Line data={this.bucketValues} />
<ReactTable
data={[...measurementsData]}
pageSize={
measurementsData.length > 10
? 10
: measurementsData.length
}
filterable
resizable={true}
columns={[
{
Header: "System",
accessor: "systemName",
},
{
Header: "Measurement",
accessor: "measurementName",
},
{
Header: "Value",
accessor: "statistics.values",
},
{
Header: "Min",
accessor: "statistics.min",
},
{
Header: "Max",
accessor: "statistics.max",
},
{
Header: "Avg",
accessor: "statistics.average",
},
{
Header: "Last",
accessor: "statistics.last",
},
{
Header: "Bar",
<Line data={this.bucketValues} />
},
]}
showPaginationTop
showPaginationBottom={false}
className="-striped -highlight"
/>
</CardBody>
</Card>
</Col>
</Row>
</div>
</>
);
}
}
export default Table;
ОБНОВЛЕНИЕ: обновил код деструктуризации ниже, и теперь я получаю"buckets" is undefined
const {
statistics: {
buckets: {
values: [bucketValues],
},
},
} = measurementsData;
console.log(bucketValues);
1 ответ
Вы уже поддерживаете состояние загрузки, используйте его для возврата загрузчика и доступа к соответствующим переменным только после того, как данные будут фактически доступны.
Также обратите внимание, что measureData - это массив, а не объект, поэтому вам нужно разрушить его как единое целое. Это предполагает тот факт, что все bucketValues в каждом объекте measureData будут одинаковыми.
constructor(props) {
super(props);
this.state = {
measurementsData: [],
isLoading: true, // set to true initially
dropdownOpen: false,
};
}
...
render() {
const { dropdownOpen, measurementsData, isLoading } = this.state;
if(isLoading) {
return <div>Loading...</div>
}
const {
measurementsData: [{
statistics: {buckets: {values: bucketValues}}
}],
} = this.state;
console.log(bucketValues);
Также lineData должен использовать bucketValues
и нет this.bucketValues
поскольку вы не храните это значение в переменной класса
<Line data={bucketValues} />