#javascript #reactjs
#javascript #reactjs
Вопрос:
У меня есть компонент React, который выполняет вызов API с использованием Axios на основе выбранного диапазона дат, который обновляется в состоянии с использованием setState. Я знаю, что поведение setState является асинхронным, поэтому я использовал подход функции стрелки, но безуспешно, состояние компонента не обновляется, в результате вызовы API завершаются неудачно. Ниже приведен фрагмент кода, который я использую:
class InterfaceDetailsDialog extends React.Component {
state = {
fromDate: null,
toDate: null,
isForADate: true
};
componentDidMount() {
this.setState({ open: true });
}
handleChangeDates = (fromDte, toDte) => {
console.log("Handle Date Change");
console.log(fromDte);
console.log(toDte);
this.setState(
{
isForADate: false,
fromDate: fromDte,
toDate: toDte
},
() => {
this.props.onInterfaceStats(
this.props.data.id,
this.state.fromDate.format("DD-MM-YYYY"),
this.state.toDate.format("DD-MM-YYYY")
);
}
);
console.log("In Set State", this.state.fromDate, ",", this.state.toDate);
};
handleSubmit = event => {
event.preventDefault();
};
handleShowTodaysData = () => {
// this.props.clearUtilizationForVxc();
this.setState({ isForADate: true }, this.refreshData);
};
renderGraph() {
if (this.state.isForADate) {
console.log(this.props.dte);
return <DetailedChart data={this.props.data.points} threshold="" />;
} else {
console.log(this.props.utilizationForInterface);
return <DetailedChart data={this.props.utilizationForInterface} />;
}
}
displayHeader() {
return (
<div>
<div
class="row"
style={{
fontFamily:
"HelveticaNeue-Light, Helvetica Neue Light, Helvetica Neue, Helvetica, Arial, Lucida Grande, sans-serif",
padding: "10px",
fontSize: "1rem",
fontWeight: "400"
}}
>
<div className="col-md-6 ">
<div
class="row"
style={{
fontFamily:
"HelveticaNeue-Light, Helvetica Neue Light, Helvetica Neue, Helvetica, Arial, Lucida Grande, sans-serif",
padding: "10px",
color: "#595959"
}}
>
{/* <div class="col-md-12">Megaport Name: {this.props.data.Megaport_Name}</div> */}
</div>
<div class="row" style={{ padding: "10px", color: "#595959" }}>
<div class="col-md-12">
Interface Name: {this.props.data.interface_name}
</div>
</div>
</div>
<div class="col-md-4">
<div class="container-fluid">
<div class="row" style={{ padding: "10px" }}>
<div style={{ color: "#595959" }}> Choose Date Range </div>
</div>
<DateRangePickerWrapper setDates={this.handleChangeDates} />
</div>
</div>
<div class="col-md-2">
<div class="container-fluid">
<div class="row" style={{ padding: "10px" }}>
<Button
onClick={this.handleShowTodaysData}
variant="outlined"
color="secondary"
>
Today's data
</Button>
</div>
</div>
</div>
</div>
</div>
);
}
displayFooter() {
return (
<div>
<div
class="container-fluid"
style={{
fontFamily:
"HelveticaNeue-Light, Helvetica Neue Light, Helvetica Neue, Helvetica, Arial, Lucida Grande, sans-serif",
padding: "10px",
fontSize: "1rem",
fontWeight: "400"
}}
>
<div class="row">
<div class="col-md-4">
Time period : {this.state.isForADate amp;amp; this.props.dte}{" "}
{!this.state.isForADate amp;amp;
this.state.fromDate.format("DD-MM-YYYY")}{" "}
{!this.state.isForADate amp;amp; <label>-</label>}{" "}
{!this.state.isForADate amp;amp; this.state.toDate.format("DD-MM-YYYY")}
</div>
{/* <div class="col-md-4">Region: {this.props.data.region}</div> */}
{/* <div class="col-md-4">Path: {this.props.data.path} </div> */}
</div>
<div class="row">
{/* <div class="col-md-4">Provisioned Date: {this.props.data.Provisioned_Date}</div> */}
{/* <div class="col-md-4">Provisioning Status: {this.props.data.Provisioning_Status}</div> */}
</div>
</div>
</div>
);
}
render() {
return (
<div color="#595959">
<Dialog
ref="dialog"
open={this.props.dialogStatus}
onClose={this.props.handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
fullWidth={true}
maxWidth={"md"}
>
{this.displayHeader()}
{this.renderGraph()}
<DialogContent>
<DialogContentText id="alert-dialog-description">
{this.displayFooter()}
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={this.props.handleClose} color="primary">
Close
</Button>
</DialogActions>
</Dialog>
</div>
);
}
}
const mapStateToProps = state => {
console.log(state.singleInterfaceStats);
return {
utilizationForInterface: state.singleInterfaceStats.single_interface_data
};
};
const mapDispatchToProps = dispatch => {
console.log("Dispatch");
return {
onInterfaceStats: (id, from_date, to_date) =>
dispatch(actionCreators.interfaceStatsByID(id, from_date, to_date))
// clearUtilizationForVxc : () => dispatch(actionCreators.clearUtilizationForVxc())
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(InterfaceDetailsDialog);
Я не могу понять, почему состояние не обновляется.
Ответ №1:
Сначала вы обновляете состояние, а затем просто передаете fromDte
и toDte
вместо this.state.fromDte
и `this.state .toDte.
this.setState(
{
isForADate: false,
fromDate: fromDte,
toDate: toDte
});
this.props.onInterfaceStats(
this.props.data.id,
fromDte.format("DD-MM-YYYY"),
toDte.format("DD-MM-YYYY")
);
Что я бы порекомендовал вам, так это то, что вы проходите fromDte
и toDte
как есть, без .format('DD-MM-YY')
. Вы выполняете этот формат внутри onInterfaceStats
функции.
Ответ №2:
в render
функции handleChangeDates
должно быть binded
to this
.
<DateRangePickerWrapper setDates={this.handleChangeDates} />
Для
<DateRangePickerWrapper setDates={this.handleChangeDates.bind(this)} />
если componentDidMount
он тоже не обновляется state
, вам нужно будет создать constructor
и назначить componentDidMount
componentDidMount.bind(this)
.
Комментарии:
1. Но если вы используете функцию со стрелкой, нет необходимости привязываться к этому
Ответ №3:
попробуйте сделать:
this.setState(
{
isForADate: false,
fromDate: Object.assign({}, fromDte),
toDate: Object.assign({}, toDte)
},
...
)
вместо:
{
isForADate: false,
fromDate: fromDte,
toDate: toDte
},
Комментарии:
1. Я попробовал этот подход, все еще не работает, любая другая идея