我在此文件中使用Redux,但单击第二个组件时出现此错误。
警告:无法在已卸载的组件上执行React状态更新。 这是空操作,但它表明应用程序中发生内存泄漏。 要修复,请取消所有订阅和异步任务 componentWillUnmount方法。
此文件特定,我在下面共享了它的代码。
import React, { Component } from "react";
import { CSVLink } from "react-csv";
import moment from "moment";
import { connect } from "react-redux";
import axios from "axios";
import { fetchAllCustomerData } from "../../actions/customer";
import SaleTables from "./SaleTables";
import { DateRangePicker } from "react-dates";
import "react-dates/initialize";
import "react-dates/lib/css/_datepicker.css";
import Pagination from "rc-pagination";
import "rc-pagination/assets/index.css";
import Loader from "react-loader-spinner";
import "./style.css";
import { Tooltip } from "reactstrap";
class CustomerReport extends Component {
constructor(props) {
super(props);
this.state = {
loading: true,
pageNumber: 1,
bySearch: "",
cityName: "",
tooltipOpen: false,
branches: [],
branchLoad: false,
agentShow: false,
dateShow: true,
agents: [],
status: "fetchAll",
url: "/api/customer/all?limit=10",
branchValue: "",
searchInput: "",
csvData: [],
focusedInput: null,
sureDate: false
};
}
headers = [
{
label: "id",
key: "id"
},
{
label: "Name",
key: "firstName"
},
{
label: "Phone",
key: "contact1"
},
{
label: "Email",
key: "email"
},
{
label: "CNIC",
key: "cnic"
},
{
label: "Created",
key: "createdAt"
},
{
label: "Created by Agent",
key: "byAgent"
}
];
componentDidMount() {
this.fetchAllCustomerData();
document.title = "Customer Report";
this.getAllCustomer();
}
getAllCustomer = () => {
axios.get("/api/customer/all").then(res => {
this.setState({
csvData: res.data.rows
});
});
};
fetchAllCustomerData = (pageNumber = 1) => {
this.setState({
pageNumber
});
const { url } = this.state;
this.props.fetchCustomers(pageNumber, url);
};
handleSearchBy = e => {
const { value } = e.target;
this.setState({
bySearch: value
});
};
handleCity = e => {
const { value } = e.target;
axios.get(`/api/officeBranch/?searchBy=city&q=${value}`).then(res => {
this.setState({
branches: res.data.rows,
branchLoad: true,
url: this.state.url
});
});
};
handleChange = e => {
this.setState({
searchInput: e.target.value
});
};
submitHandle = (e, pageNumber = 1) => {
e.preventDefault();
const url = `/api/customer/all?searchBy=id&offset=0&limit=10&q=${this.state.searchInput}`;
this.setState({
url
});
this.props.fetchCustomers(pageNumber, url);
};
fetchAgents = (e, pageNumber = 1) => {
const { value } = e.target;
let split = value.split(",");
let url = `/api/customer/all?searchBy=branch&q=${split[1]}&limit=10`;
this.setState({
url,
pageNumber: 1
});
axios
.get(`/api/officebranch/branchAgents?officeBranchId=${value}`)
.then(res => {
this.setState({
agents: res.data.rows,
agentShow: true
});
});
this.props.fetchCustomers(pageNumber, url);
};
toggle = () => {
this.setState({
tooltipOpen: !this.state.tooltipOpen
});
};
loadAgents = (e, pageNumber = 1) => {
const { value } = e.target;
const url = `/api/customer/all?searchBy=agent&q=${value}&limit=10`;
this.setState({
url,
pageNumber: 1
});
this.props.fetchCustomers(pageNumber, url);
};
handleDatesChange = (startDate, endDate, pageNumber = 1) => {
if (startDate !== "" && endDate !== "") {
let url = `/api/customer/all?fromDate=${startDate.format(
"YYYY-MM-DD"
)}&toDate=${endDate.format("YYYY-MM-DD")}`;
this.setState({
url,
sureDate: true,
pageNumber: 1,
startDate: startDate,
endDate: endDate
});
this.props.fetchCustomers(pageNumber, url);
}
};
render() {
const { customer_users, isLoading, status, cities } = this.props;
const {
bySearch,
branchLoad,
branches,
agentShow,
agents,
startDate,
endDate,
sureDate
} = this.state;
let csvCustomerData = this.state.csvData.map(row => ({
...row,
firstName: row.firstName + " " + row.lastName,
createdAt: moment(row.createdAt).format("YYYY-MM-DD"),
byAgent: row.user.firstName + " " + row.user.lastName,
cnic: `=""${row.cnic}""`
}));
let csvFilterCustomerData =
customer_users &&
customer_users.data.rows.map(row => ({
...row,
firstName: row.firstName + " " + row.lastName,
createdAt: moment(row.createdAt).format("YYYY-MM-DD"),
byAgent: row.user.firstName + " " + row.user.lastName,
cnic: `=""${row.cnic}""`
}));
return (
<div>
{customer_users && customer_users.data.rows ? (
<div className="pillsWrap">
{/* Filters HTML */}
<div className="filtersMain">
<div className="row">
<div className="col-md-12">
<div className="row">
<div className="col-md-2">
<div className="officeFilter">
<select
className="browser-default custom-select marginArea"
onChange={this.handleSearchBy}
>
<option> By </option>
<option value="id"> Id </option>
<option value="agent"> Agent </option>
</select>
</div>
</div>
{bySearch === "id" ? (
<div className="col-md-6">
<form onSubmit={this.submitHandle}>
<input
type="text"
name="search"
placeholder="Search.."
className="searchBox"
onChange={this.handleChange}
autoComplete="off"
/>
</form>
</div>
) : null}
{bySearch === "id" || bySearch === "agent" ? null : (
<div className="col-md-10 pull-right">
<div className="dateFilter">
<DateRangePicker
startDate={moment(startDate)}
endDate={moment(endDate)}
onDatesChange={dateData => {
this.handleDatesChange(
dateData.startDate,
dateData.endDate
);
}}
focusedInput={this.state.focusedInput}
onFocusChange={focusedInput =>
this.setState({ focusedInput })
}
startDateId="TASKS_FILTER_START_DATE_UNIQUE_ID"
endDateId="TASKS_FILTER_END_DATE_UNIQUE_ID"
numberOfMonths={1}
isOutsideRange={day => false}
displayFormat="MMM DD / YY"
/>
</div>
</div>
)}
{bySearch === "agent" ? (
<div className="col-md-2">
<select
className="browser-default custom-select marginArea"
onChange={this.handleCity}
>
<option>By City</option>
{cities.data.map(item => (
<option value={item.name} key={item.id}>
{item.name}
</option>
))}
</select>
</div>
) : null}
{bySearch === "agent" && branchLoad ? (
<div className="col-md-2">
<select
className="browser-default custom-select marginArea"
onChange={this.fetchAgents}
>
<option>By Branch</option>
{branches.map(item => (
<option
value={item.id + "," + item.branchName}
key={item.id}
>
{item.branchName}
</option>
))}
</select>
</div>
) : null}
{bySearch === "agent" && branchLoad && agentShow ? (
<div className="col-md-2">
<select
className="browser-default custom-select marginArea"
onChange={this.loadAgents}
>
<option>By Agent</option>
{agents.map(item => (
<option
value={item.firstName + " " + item.lastName}
key={item.id}
>
{item.firstName + " " + item.lastName}
</option>
))}
</select>
</div>
) : null}
{/* Row End */}
</div>
<div className="row">
{sureDate ? (
<div className="col-md-10 mb-4">
{" "}
<CSVLink
data={csvFilterCustomerData}
headers={this.headers}
filename="customer_report.csv"
>
<i
className="fa fa-download agencyDefualt"
id="TooltipExample"
></i>
<Tooltip
placement="right"
isOpen={this.state.tooltipOpen}
target="TooltipExample"
toggle={this.toggle}
>
export filter customers report
</Tooltip>
</CSVLink>
</div>
) : (
<div className="col-md-10 mb-4">
{" "}
<CSVLink
data={csvCustomerData}
headers={this.headers}
filename="customer_report.csv"
>
<i
className="fa fa-download agencyDefualt"
id="TooltipExample"
></i>
<Tooltip
placement="right"
isOpen={this.state.tooltipOpen}
target="TooltipExample"
toggle={this.toggle}
>
export customers report
</Tooltip>
</CSVLink>
</div>
)}
</div>
{isLoading ? (
<div
style={{
marginTop: "20px"
}}
className="text-center"
>
<h3 className="dimgray"> Loading Customers </h3>{" "}
<p className="dimgray"> Hold Your Horses! </p>{" "}
<Loader
type="ThreeDots"
color="#7AC953"
height="40"
width="40"
/>
</div>
) : customer_users && customer_users.data.rows.length ? (
<>
{" "}
<div className="data-showing">
Showing - {(this.state.pageNumber - 1) * 10 + 1}-
{this.state.pageNumber * 10 >= customer_users.data.count
? customer_users.data.count
: this.state.pageNumber * 10 + " "}{" "}
/ {customer_users.data.count}
</div>{" "}
<SaleTables
status={status}
customerReport={customer_users}
/>
<div className="text-center">
{sureDate ? null : (
<>
<Pagination
className={"paginationCustomStyle"}
onChange={this.fetchAllCustomerData}
current={this.state.pageNumber}
total={customer_users.data.count}
/>
</>
)}
</div>
</>
) : (
<div style={{ marginTop: "20px" }} className="text-center">
<h3 className="dimgray">No Customers Found</h3>
<p className="dimgray">
You Have Not Added Any Customers
</p>
</div>
)}
</div>
</div>
</div>
</div>
) : null}
</div>
);
}
}
const mapStateToProps = state => {
return {
customer_users: state.Customer.allFilterCustomers,
isLoading: state.Customer.isLoading,
status: state.Customer.status,
cities: state.Customer.cities
};
};
const mapDispatchToProps = dispatch => {
return {
fetchCustomers: (page, url) => dispatch(fetchAllCustomerData(page, url))
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(CustomerReport);
答案 0 :(得分:1)
可能是因为您在componentDidMount方法中进行了AJAX调用(getAllCustomer)。如果在卸载组件时响应到达,则resolve回调中的setState将引发React警告。您最好在组件的componentWillUnmount方法中取消所有正在进行的AJAX调用。您可以使用Axios进行此操作:https://github.com/axios/axios#cancellation
您可以尝试以下操作:
import React, { Component } from "react";
import { CSVLink } from "react-csv";
import moment from "moment";
import { connect } from "react-redux";
import axios from "axios";
import { fetchAllCustomerData } from "../../actions/customer";
import SaleTables from "./SaleTables";
import { DateRangePicker } from "react-dates";
import "react-dates/initialize";
import "react-dates/lib/css/_datepicker.css";
import Pagination from "rc-pagination";
import "rc-pagination/assets/index.css";
import Loader from "react-loader-spinner";
import "./style.css";
import { Tooltip } from "reactstrap";
class CustomerReport extends Component {
constructor(props) {
super(props);
this.cancelTokenSource = new axios.CancelToken.source();
this.state = {
loading: true,
pageNumber: 1,
bySearch: "",
cityName: "",
tooltipOpen: false,
branches: [],
branchLoad: false,
agentShow: false,
dateShow: true,
agents: [],
status: "fetchAll",
url: "/api/customer/all?limit=10",
branchValue: "",
searchInput: "",
csvData: [],
focusedInput: null,
sureDate: false
};
}
headers = [
{
label: "id",
key: "id"
},
{
label: "Name",
key: "firstName"
},
{
label: "Phone",
key: "contact1"
},
{
label: "Email",
key: "email"
},
{
label: "CNIC",
key: "cnic"
},
{
label: "Created",
key: "createdAt"
},
{
label: "Created by Agent",
key: "byAgent"
}
];
componentDidMount() {
this.fetchAllCustomerData();
document.title = "Customer Report";
this.getAllCustomer();
}
componentWillUnmount () {
this.cancelTokenSource.cancel()
}
getAllCustomer = () => {
axios.get("/api/customer/all", { cancelToken: this.cancelTokenSource.token })
.then(res => {
this.setState({
csvData: res.data.rows
});
})
.catch(e => {
if (axios.isCancel(e)) {
console.log('Axios call cancelled !')
}
});
};
fetchAllCustomerData = (pageNumber = 1) => {
this.setState({
pageNumber
});
const { url } = this.state;
this.props.fetchCustomers(pageNumber, url);
};
handleSearchBy = e => {
const { value } = e.target;
this.setState({
bySearch: value
});
};
handleCity = e => {
const { value } = e.target;
axios.get(`/api/officeBranch/?searchBy=city&q=${value}`).then(res => {
this.setState({
branches: res.data.rows,
branchLoad: true,
url: this.state.url
});
});
};
handleChange = e => {
this.setState({
searchInput: e.target.value
});
};
submitHandle = (e, pageNumber = 1) => {
e.preventDefault();
const url = `/api/customer/all?searchBy=id&offset=0&limit=10&q=${this.state.searchInput}`;
this.setState({
url
});
this.props.fetchCustomers(pageNumber, url);
};
fetchAgents = (e, pageNumber = 1) => {
const { value } = e.target;
let split = value.split(",");
let url = `/api/customer/all?searchBy=branch&q=${split[1]}&limit=10`;
this.setState({
url,
pageNumber: 1
});
axios
.get(`/api/officebranch/branchAgents?officeBranchId=${value}`)
.then(res => {
this.setState({
agents: res.data.rows,
agentShow: true
});
});
this.props.fetchCustomers(pageNumber, url);
};
toggle = () => {
this.setState({
tooltipOpen: !this.state.tooltipOpen
});
};
loadAgents = (e, pageNumber = 1) => {
const { value } = e.target;
const url = `/api/customer/all?searchBy=agent&q=${value}&limit=10`;
this.setState({
url,
pageNumber: 1
});
this.props.fetchCustomers(pageNumber, url);
};
handleDatesChange = (startDate, endDate, pageNumber = 1) => {
if (startDate !== "" && endDate !== "") {
let url = `/api/customer/all?fromDate=${startDate.format(
"YYYY-MM-DD"
)}&toDate=${endDate.format("YYYY-MM-DD")}`;
this.setState({
url,
sureDate: true,
pageNumber: 1,
startDate: startDate,
endDate: endDate
});
this.props.fetchCustomers(pageNumber, url);
}
};
render() {
const { customer_users, isLoading, status, cities } = this.props;
const {
bySearch,
branchLoad,
branches,
agentShow,
agents,
startDate,
endDate,
sureDate
} = this.state;
let csvCustomerData = this.state.csvData.map(row => ({
...row,
firstName: row.firstName + " " + row.lastName,
createdAt: moment(row.createdAt).format("YYYY-MM-DD"),
byAgent: row.user.firstName + " " + row.user.lastName,
cnic: `=""${row.cnic}""`
}));
let csvFilterCustomerData =
customer_users &&
customer_users.data.rows.map(row => ({
...row,
firstName: row.firstName + " " + row.lastName,
createdAt: moment(row.createdAt).format("YYYY-MM-DD"),
byAgent: row.user.firstName + " " + row.user.lastName,
cnic: `=""${row.cnic}""`
}));
return (
<div>
{customer_users && customer_users.data.rows ? (
<div className="pillsWrap">
{/* Filters HTML */}
<div className="filtersMain">
<div className="row">
<div className="col-md-12">
<div className="row">
<div className="col-md-2">
<div className="officeFilter">
<select
className="browser-default custom-select marginArea"
onChange={this.handleSearchBy}
>
<option> By </option>
<option value="id"> Id </option>
<option value="agent"> Agent </option>
</select>
</div>
</div>
{bySearch === "id" ? (
<div className="col-md-6">
<form onSubmit={this.submitHandle}>
<input
type="text"
name="search"
placeholder="Search.."
className="searchBox"
onChange={this.handleChange}
autoComplete="off"
/>
</form>
</div>
) : null}
{bySearch === "id" || bySearch === "agent" ? null : (
<div className="col-md-10 pull-right">
<div className="dateFilter">
<DateRangePicker
startDate={moment(startDate)}
endDate={moment(endDate)}
onDatesChange={dateData => {
this.handleDatesChange(
dateData.startDate,
dateData.endDate
);
}}
focusedInput={this.state.focusedInput}
onFocusChange={focusedInput =>
this.setState({ focusedInput })
}
startDateId="TASKS_FILTER_START_DATE_UNIQUE_ID"
endDateId="TASKS_FILTER_END_DATE_UNIQUE_ID"
numberOfMonths={1}
isOutsideRange={day => false}
displayFormat="MMM DD / YY"
/>
</div>
</div>
)}
{bySearch === "agent" ? (
<div className="col-md-2">
<select
className="browser-default custom-select marginArea"
onChange={this.handleCity}
>
<option>By City</option>
{cities.data.map(item => (
<option value={item.name} key={item.id}>
{item.name}
</option>
))}
</select>
</div>
) : null}
{bySearch === "agent" && branchLoad ? (
<div className="col-md-2">
<select
className="browser-default custom-select marginArea"
onChange={this.fetchAgents}
>
<option>By Branch</option>
{branches.map(item => (
<option
value={item.id + "," + item.branchName}
key={item.id}
>
{item.branchName}
</option>
))}
</select>
</div>
) : null}
{bySearch === "agent" && branchLoad && agentShow ? (
<div className="col-md-2">
<select
className="browser-default custom-select marginArea"
onChange={this.loadAgents}
>
<option>By Agent</option>
{agents.map(item => (
<option
value={item.firstName + " " + item.lastName}
key={item.id}
>
{item.firstName + " " + item.lastName}
</option>
))}
</select>
</div>
) : null}
{/* Row End */}
</div>
<div className="row">
{sureDate ? (
<div className="col-md-10 mb-4">
{" "}
<CSVLink
data={csvFilterCustomerData}
headers={this.headers}
filename="customer_report.csv"
>
<i
className="fa fa-download agencyDefualt"
id="TooltipExample"
></i>
<Tooltip
placement="right"
isOpen={this.state.tooltipOpen}
target="TooltipExample"
toggle={this.toggle}
>
export filter customers report
</Tooltip>
</CSVLink>
</div>
) : (
<div className="col-md-10 mb-4">
{" "}
<CSVLink
data={csvCustomerData}
headers={this.headers}
filename="customer_report.csv"
>
<i
className="fa fa-download agencyDefualt"
id="TooltipExample"
></i>
<Tooltip
placement="right"
isOpen={this.state.tooltipOpen}
target="TooltipExample"
toggle={this.toggle}
>
export customers report
</Tooltip>
</CSVLink>
</div>
)}
</div>
{isLoading ? (
<div
style={{
marginTop: "20px"
}}
className="text-center"
>
<h3 className="dimgray"> Loading Customers </h3>{" "}
<p className="dimgray"> Hold Your Horses! </p>{" "}
<Loader
type="ThreeDots"
color="#7AC953"
height="40"
width="40"
/>
</div>
) : customer_users && customer_users.data.rows.length ? (
<>
{" "}
<div className="data-showing">
Showing - {(this.state.pageNumber - 1) * 10 + 1}-
{this.state.pageNumber * 10 >= customer_users.data.count
? customer_users.data.count
: this.state.pageNumber * 10 + " "}{" "}
/ {customer_users.data.count}
</div>{" "}
<SaleTables
status={status}
customerReport={customer_users}
/>
<div className="text-center">
{sureDate ? null : (
<>
<Pagination
className={"paginationCustomStyle"}
onChange={this.fetchAllCustomerData}
current={this.state.pageNumber}
total={customer_users.data.count}
/>
</>
)}
</div>
</>
) : (
<div style={{ marginTop: "20px" }} className="text-center">
<h3 className="dimgray">No Customers Found</h3>
<p className="dimgray">
You Have Not Added Any Customers
</p>
</div>
)}
</div>
</div>
</div>
</div>
) : null}
</div>
);
}
}
const mapStateToProps = state => {
return {
customer_users: state.Customer.allFilterCustomers,
isLoading: state.Customer.isLoading,
status: state.Customer.status,
cities: state.Customer.cities
};
};
const mapDispatchToProps = dispatch => {
return {
fetchCustomers: (page, url) => dispatch(fetchAllCustomerData(page, url))
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(CustomerReport);