在我的 React 组件中,我希望我的状态自动更新而无需重新加载页面。我正在使用 lodash.iseqaual 方法来比较状态变化,但这不会更新状态。
下面是我的组件:
import React, { Component } from "react";
import { Link } from "react-router-dom";
import axios from "axios";
import $ from "jquery";
import isEqual from "lodash/isEqual";
$.DataTable = require("datatables.net");
class Active extends Component {
state = {
activeData: [],
flag: 0,
isLoading: true
};
componentDidMount() {
this.getActiveData();
}
componentDidUpdate(prevProps, prevState) {
if (!isEqual(prevState.activeData, this.state.activeData)) {
this.getActiveData();
}
}
getActiveData() {
const params = new FormData();
params.append("status", "active");
axios.post("http://127.0.0.1:8000/details/", params).then(res => {
if (res.data.result === 1) {
this.setState({
activeData: res.data.data,
flag: 1,
isLoading: false
});
if (!this.state.isLoading) {
this.initTable();
}
} else if (res.data.result === 0) {
this.setState({ isLoading: false });
this.initTable();
}
});
}
initTable() {
$("#Active_Datatable").DataTable();
}
render() {
if (this.state.isLoading) {
return (
<img
alt="loading"
src="https://upload.wikimedia.org/wikipedia/commons/b/b1/Loading_icon.gif"
/>
);
}
return (
<React.Fragment>
<div className="panel-heading" role="tab" id="heading3">
<a
href="#Current"
className="collapsed text-left textuppercase"
role="button"
data-toggle="collapse"
data-parent="tabs-content"
aria-expanded="true"
aria-controls="Current"
>
<i className="fas fa-list-ul" /> Current
<i className="fas fa-chevron-down pull-right" />
</a>
</div>
<div
id="Current"
role="tabpanel"
className="tab-pane panel-collapse collapse"
aria-labelledby="heading3"
>
<table
id="Active_Datatable"
className="display"
style={{ width: "100%" }}
>
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Open</th>
<th>Close</th>
<th>Price</th>
</tr>
</thead>
{this.state.flag === 1 ? (
<tbody>
{this.state.activeData.map((ac, i) => (
<tr key={sc.id}>
<td className="text-center">{i + 1}</td>
<td>
<Link
to={{
pathname: `/${ac.name_slug}/`,
state: {
id: ac.id,
name: ac.name
}
}}
>
{sc.name}
</Link>
</td>
<td>{sc.open_date}</td>
<td>{sc.close_date}</td>
<td>
{Number(sc.price).toLocaleString("en-IN", {
currency: "INR"
})}
</td>
</tr>
))}
</tbody>
) : null}
</table>
</div>
</React.Fragment>
);
}
}
export default Active;
lodash.isequal
incomponentDidUpdate()
方法没有更新我的状态。
我还在componentDidUpdate中尝试了以下逻辑:
componentDidUpdate(prevProps, prevState) {
if (prevState.activeData !== this.state.activeData) {
this.getActiveData();
}
}
但这会进入无限循环,即使在没有变化之后也会增加 API 调用。
我怎样才能做到这一点?
提前致谢!
**需要等待这个问题的解决方案。
更新:
从所有答案中,我想我应该用示例来解释。因此,当我进行 API 调用并更新状态activeData
时,它更新为:
[
{
id: 1
name: "ABC"
close_date: "2019-01-11"
open_date: "2019-01-08"
price: "80"
},
{
id: 2
name: "XYZ"
close_date: "2019-01-12"
open_date: "2019-01-04"
price: "80"
}
]
例如,如果我将名称字段从更新为ABC
返回ABCD
的结果将是:
[
{
id: 1
name: "ABCD"
close_date: "2019-01-11"
open_date: "2019-01-08"
price: "80"
},
{
id: 2
name: "XYZ"
close_date: "2019-01-12"
open_date: "2019-01-04"
price: "80"
}
]
然后组件中的名称值应自动从 ABC 更新为 ABCD,无需重新加载页面。
这不会发生在任何一个shouldComponentUpdate
或通过按照建议更改我的 lodash 语法的情况下。
目录结构:
project
|- public
|- src
-components
-Header_Footer
Header.jsx
Footer.jsx
-Home
index.jsx
-Details
Active.jsx
Upcoming.jsx
App.js
index.js
另外我会告诉我的组件是如何呈现的:
详细信息.jsx
import React, { Component } from "react";
import Active from "./Active";
import Upcoming from "./Upcoming";
class Details extends Component {
render() {
return (
<div className="col-md-9 col-sm-9 col-xs-12">
<div className="right_panel">
<h2>Listing</h2>
<div className="responsive-tabs text-center ">
<ul className="nav nav-tabs" role="tablist">
<li role="presentation" className="active">
<a
href="#Upcoming"
aria-controls="Upcoming"
role="tab"
data-toggle="tab"
>
Upcoming
</a>
</li>
<li role="presentation" className="">
<a
href="#Current"
aria-controls="Current"
role="tab"
data-toggle="tab"
>
Current
</a>
</li>
</ul>
<div
id="tabs-content"
className="tab-content panel-group table-responsive"
>
<Upcoming />
<Active />
</div>
</div>
</div>
</div>
);
}
}
export default Details;
主页.js
import React, { Component } from "react";
import Sidebar from "./Sidebar";
import Details from "./details";
class Home extends Component {
render() {
return (
<div className="container container_padding">
<div className="row">
<Sidebar />
<Details />
</div>
</div>
);
}
}
export default Home;
应用程序.js
import React, { Component } from "react";
import { Router, Route, Switch } from "react-router-dom";
import Header from "./components/Header_Footer/Header";
import Footer from "./components/Header_Footer/Footer";
import Home from "./components/Home";
import createBrowserHistory from "history/createBrowserHistory";
const history = createBrowserHistory();
class App extends Component {
render() {
return (
<Router history={history}>
<React.Fragment>
<Header />
<Switch>
<Route exact path="/" component={Home} />
</Switch>
<Footer />
</React.Fragment>
</Router>
);
}
}
export default App;