0
votes

I am trying to write React Component with DataTable and react-switch.

It seems it working, but when I see the developer console, there is 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.

The error shows only when I "drag" the Switch. If I only click on the switch, there is no error.

import React from 'react';
import { authenticationService } from '../../helpers/AuthenticationService';
import axios from 'axios';
import DataTable from 'react-data-table-component';
import Switch from "react-switch";


class ProductEshop extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            isCancelled: false,
            data: [],
            checked: false
        }
    }


    handleButtonClick = (state, row) => {

    this.setState({
            data: this.state.data.map((item, index) =>
                item.eshopId == row.eshopId ? { ...item, isActive: !item.isActive } : item,
            )
     })
    };

    componentDidMount() {
        const currentUser = authenticationService.currentUserValue;

        axios.get('/api/product/' + this.props.id + '/eshops', { headers: { "Authorization": `Bearer ${currentUser.token}` } }).then(res => {
            this.setState({ data: res.data });
        }).catch(err => {
            console.log(err);
        });
    }

    render() {
        const columns = (clickHandler => [

            {
                cell: (row) => <Switch onChange={(e) => clickHandler(e, row)} checked={row.isActive} />
            },
            {
                name: 'Název',
                selector: 'name',
                sortable: true,
            }
        ]);

        return (<div>
            <DataTable
                title="Products"
                data={this.state.data}
                columns={columns(this.handleButtonClick)}
                onRowSelected={this.handleChange}
                paginationComponentOptions={this.state.paggination}
                pagination
                dense
            />
        </div>)
    }
}

export default (ProductEshop)

Can somebody help please?

UPDATE: the error is created in handleButtonClick

1

1 Answers

0
votes

It happens because this.setState is called in an async process. This means even if you unmount the component Axios will try to execute then and that's why you get the warning. You need to cancel the request on componentWillUnmount

  componentDidMount () {
    this.axiosCancelSource = axios.CancelToken.source()

   axios.get('/api/product/' + this.props.id + '/eshops', 
  { headers: { "Authorization": `Bearer ${currentUser.token}` }, 
    cancelToken: this.axiosCancelSource.token })
   .then(res => {
            this.setState({ data: res.data });
        }).catch(err => {
            console.log(err);
      });
  }

  componentWillUnmount () {
    this.axiosCancelSource.cancel('Axios request canceled.')
  }