1
votes

I am using Redux in this file but when I click on second component I am getting this error.

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.

It's specific with this file and I have shared it's code below.

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);
1
Please don't beg in the question asking not to down vote your question. If your post is not up to the expected quality, someone may down vote it no matter how politely you asked not to do so.Pavindu
try swapping this.fetchAllCustomerData(); and this.getAllCustomer();. and as I remember document.title = "Customer Report" should be window.document.title="Customer Report"Pavindu
I think its not about redux your code seems fine., you are trying to use a component that is not mounted yet, which is not in your code, its my guessbehzad
This is your full code? Because you missing few thingsbehzad
@behzad Yes, it full code of this componentjonny

1 Answers

1
votes

It is probably because you make an AJAX call (getAllCustomer) in your componentDidMount method. If the response arrives while your component is unmounted, the setState in the resolve callback will cause the React warning. You should better cancel all ongoing AJAX call in the component's componentWillUnmount method. You can do this with Axios : https://github.com/axios/axios#cancellation

You can try something like this:

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);