title: how to cancel previous axios with redux in react
body: <p>i have the following action in my action file.</p>
  
  <pre><code>import axios from 'axios';
  import $ from 'jquery';
  var CancelToken = axios.CancelToken;
  var source = CancelToken.source();
  
  export const FETCH_WORKERJOBS = 'fetch_workerjobs';
  
  export function fetchWorkerJobs(page, size, where, sort) {
      const request = axios.get(`/api/user/report/comms/matrix/upload/format/json?quiet=1&amp;page=`+page+`&amp;size=`+size+`&amp;where=`+JSON.stringify(where)+`&amp;sort=`+sort,{cancelToken: source.token});   
      return {
          type: FETCH_WORKERJOBS,
          payload: request
      };
  }
  
  export const FETCH_WORKERJOBS_COUNT = 'fetch_workerjobs_count';
  
  export function fetchWorkerJobsCount(where) {
      const request = axios.get(`/api/user/report/comms/matrix/upload/count/format/json?quiet=1&amp;where=`+JSON.stringify(where), {cancelToken: source.token});  
      return {
          type: FETCH_WORKERJOBS_COUNT,
          payload: request
      };
  }
  </code></pre>
  
  <p>How can i access the <code>cancel</code> token to cancel when I am importing the function into my component</p>
  
  <pre><code>import _ from 'lodash';
  import React, { Component } from 'react';
  import { connect } from 'react-redux';
  import { fetchWorkerJobs, fetchWorkerJobsCount } from '../../actions';
  import { Link } from 'react-router-dom';
  import { bindActionCreators } from 'redux';
  import { Button, ButtonToolbar, Modal } from 'react-bootstrap';
  import FontAwesome from 'react-fontawesome';
  import {
      BootstrapTable,
      TableHeaderColumn,
      InsertModalHeader,
      InsertModalFooter
  } from 'react-bootstrap-table';
  import 'react-bootstrap-table/dist/react-bootstrap-table-all.min.css';
  import $ from 'jquery';
  
  const jobType = {
          }
  
  class WorkerJobs extends Component {
      constructor(props) {
          super(props);
          this.workerJobs = [];
          this.state = {
              data: [],
              show: false,
              showError: false,
              errorMsg: '',
              errorTitle: '',
              record: {},
              showEdit: false,
              confirm: {
                  body: '',
                  show: false,
                  id: ''
              },
              totalDataSize: 0,
              currentPage: 1
  
          };
          this.where = {};
          this.sort = 'worker_job_id desc';
          this.meta = { title: 'Report - Worker Jobs', description: 'List of jobs processed' };
          this.error = {show: false,msg:''};
          this.passMetaBack = this.passMetaBack.bind(this);
          this.options = {
              defaultSortName: 'worker_job_id', // default sort column name
              defaultSortOrder: 'desc', // default sort order
              page: 1,
              paginationShowsTotal: true,
              sizePerPage: 10,
              sizePerPageList: [10,25,50],
              onPageChange: this.onPageChange.bind(this),
              onSizePerPageList: this.onSizePerPageList.bind(this),
              onFilterChange: this.onFilterChange.bind(this),
              onSortChange: this.onSortChange.bind(this)
          };
  
          this.fetchWorkerJobs = this.fetchWorkerJobs.bind(this);
  
          this.runOnce = false;
      }
  
      onPageChange(page, sizePerPage) {
          const currentIndex = (page - 1) * sizePerPage;
          this.options.page = page;
          console.log(this.props);
          this.props.fetchWorkerJobsCount.cancel(); //not working
          this.props.fetchWorkerJobs.cancel(); //not working
          console.log(this.props);
          this.fetchWorkerJobs(page, sizePerPage, this.where, this.sort);
        }
  
      onSizePerPageList(sizePerPage) {
          const currentIndex = (this.state.currentPage - 1) * sizePerPage;
          this.options.sizePerPage = sizePerPage;
          this.fetchWorkerJobs(this.options.page, sizePerPage, this.where, this.sort);
        }
  
      onFilterChange(filterObj) {
  
          let where = {};
          for (const key in filterObj) {
              where[key] = filterObj[key].value;
          }
          this.where = where;
          this.fetchWorkerJobs(this.options.page,this.options.sizePerPage,this.where, this.sort);
        }
  
      onSortChange(sortName, sortOrder) {
          this.sort = sortName + " " + sortOrder;
          this.fetchWorkerJobs(this.options.page,this.options.sizePerPage,this.where, this.sort);
        }
  
  
  
      fetchWorkerJobs(page, size, where, sort){
          let self = this;   
          this.props.fetchWorkerJobsCount(where).then(function(response){
              let data = response.payload.data;
              if(data.header.error){
                  //@todo show error on input form
                  //self.handleShowError(data.header.message);                
              }else{
                  return data.body.recordset.record;
  
              }
          })
          .then((count)=&gt;{
              this.props.fetchWorkerJobs(page, size, where, sort).then(function(response){
                  let data = response.payload.data;
                  if(data.header.error){
                      //@todo show error on input form
                      //self.handleShowError(data.header.message);                
                  }else{
                      self.options.page = page;
                      self.options.sizePerPage = size;
                      self.workerJobs = data.body.recordset.record;
                      self.setState({
                          data : data.body.recordset.record,
                          totalDataSize : count
                      });
                  }
              });
          });
  
      }
  
      moveElement() {
        //store a this ref, and
        var _this = this;
        //wait for a paint to do scrolly stuff
        window.requestAnimationFrame(function() {
            if($(".react-bs-table-tool-bar").length &gt; 0){
                if($(".react-bs-table-tool-bar .react-bs-table-sizePerPage-dropdown").length &lt;= 0){
  
                    $(".react-bs-table-sizePerPage-dropdown").prependTo(".react-bs-table-tool-bar");
                }
            }
        });
      }
  
      renderTable(services) {
  
          return (
              &lt;BootstrapTable
                  keyField="worker_job_id"
                  data={services}
                  remote
                  //multiColumnSearch
                  fetchInfo={ { dataTotalSize: this.state.totalDataSize } }
                  options={this.options}
                  pagination
                  striped
                  hover
                  //insertRow
                  //search
                  tableHeaderClass="table-vf thead"
                  exportCSV
                  tableContainerClass="report_workerjobs"
              &gt;
                  &lt;TableHeaderColumn dataField="worker_job_id" dataSort={true} width={`60px`}&gt;
                      #
                  &lt;/TableHeaderColumn&gt;
                  &lt;TableHeaderColumn dataField="job" filter={ { type: 'SelectFilter', options: jobType } }&gt;Job&lt;/TableHeaderColumn&gt;
                  &lt;TableHeaderColumn dataField="filename"&gt;Filename&lt;/TableHeaderColumn&gt;
                  &lt;TableHeaderColumn
                      dataField="flag"
                      filter={{ type: 'TextFilter', defaultValue: 'C' }}
                      width={`60px`}
                  &gt;
                      Flag
                  &lt;/TableHeaderColumn&gt;
                  &lt;TableHeaderColumn dataField="total_time_taken" width={`125px`}&gt;Total Time Taken&lt;/TableHeaderColumn&gt;
                  &lt;TableHeaderColumn dataField="output" width={`100px`}&gt;Analysis&lt;/TableHeaderColumn&gt;
                  &lt;TableHeaderColumn dataField="ts_created"&gt;Created&lt;/TableHeaderColumn&gt;
                  &lt;TableHeaderColumn dataField="ts_updated"&gt;Finished&lt;/TableHeaderColumn&gt;     
                  &lt;TableHeaderColumn dataField="comms_matrix_id" width={`60px`}&gt;#CM&lt;/TableHeaderColumn&gt;
                  &lt;TableHeaderColumn dataField="visible_lines" width={`100px`}&gt;Visible Lines&lt;/TableHeaderColumn&gt;
                  &lt;TableHeaderColumn 
                      dataField="security_flows" 
                      width={`100px`} 
                      thStyle={{
                          whiteSpace: 'pre-wrap',
                          whiteSpace: '-moz-pre-wrap',
                          whiteSpace: '-pre-wrap',
                          whiteSpace: '-o-pre-wrap',
                          wordWrap: 'break-word'
                          }} 
                  &gt;
                      Security Flows
                  &lt;/TableHeaderColumn&gt;
  
              &lt;/BootstrapTable&gt;
          );
      }
  
      render() {
          if(!this.runOnce &amp;&amp; this.props.isReady){             
              this.runOnce = true;
              this.fetchWorkerJobs(this.options.page, this.options.sizePerPage, this.where, this.sort);
          }
  
          let table = &lt;div&gt;Loading...&lt;i className="fa fa-spinner fa-spin"&gt;&lt;/i&gt;&lt;/div&gt;;
          if ( Object.keys(this.props.reportsWorkerJobs).length &gt; 0) {
              table = this.renderTable(this.state.data);
              this.moveElement();
          }
  
          return (
              &lt;div className="container-fluid"&gt;
                  &lt;div className="row-fluid top-buffer"&gt;{table}&lt;/div&gt;
              &lt;/div&gt;
          );
      }
  }
  
  function mapStateToProps(state) {
  
      return {
          reportsWorkerJobs: state.reportsWorkerJobs,
          reportsWorkerJobsCount: state.reportsWorkerJobsCount
      };
  }
  
  function mapDispatchToProps(dispatch) {
      return bindActionCreators(
          { fetchWorkerJobs, fetchWorkerJobsCount },
          dispatch
      );
  }
  
  export default connect(mapStateToProps, mapDispatchToProps)(WorkerJobs);
  </code></pre>
  
  <p>I want to cancel previous pagination requests etc.. I need to cancel</p>
  
  <pre><code>this.props.fetchWorkerJobsCount.cancel(); //not working
          this.props.fetchWorkerJobs.cancel(); //not working
  </code></pre>
  
  <p>I have tried to export the variable from action file and import into component but that does not work</p>
  
  <p><strong>actions.js</strong></p>
  
  <pre><code>export const FETCH_WORKERJOBS_COUNT_CANCEL = wjc_cancel;
  </code></pre>
  
  <p><strong>component</strong></p>
  
  <pre><code>...
  import { fetchWorkerJobs, fetchWorkerJobsCount, FETCH_WORKERJOBS_COUNT_CANCEL, FETCH_WORKERJOBS_CANCEL } from '../../actions';
  ...
  onPageChange(page, sizePerPage) {
          const currentIndex = (page - 1) * sizePerPage;
          this.options.page = page;
          FETCH_WORKERJOBS_COUNT_CANCEL();
          FETCH_WORKERJOBS_CANCEL();
          this.fetchWorkerJobs(page, sizePerPage, this.where, this.sort);
        }
  </code></pre>
  
  <p>error i get is <code>Uncaught TypeError: (0 , _actions.FETCH_WORKERJOBS_COUNT_CANCEL) is not a function</code></p>
  
  <p>Update</p>
  
  <p>I tried to pass it as variable to actions function but some requests seem to get through. what I am doing is pressing the next button on pagination very fast. most get cancelled but some do not.</p>
  
  <p><a href="https://i.stack.imgur.com/EfIMV.png" rel="noreferrer"><img src="https://i.stack.imgur.com/EfIMV.png" alt="some not being cancelled fast enough"></a></p>
  
  <pre><code>export function fetchWorkerJobs(page, size, where, sort, cancelled) {
      if(cancelled){
          wj_cancel();
  
      }
      const request = axios.get(`/api/user/report/comms/matrix/upload/format/json?quiet=1&amp;page=`+page+`&amp;size=`+size+`&amp;where=`+JSON.stringify(where)+`&amp;sort=`+sort,{
          cancelToken: new CancelToken(function executor(c) {
              // An executor function receives a cancel function as a parameter
              wj_cancel = c;
          })
      }); 
      return {
          type: FETCH_WORKERJOBS,
          payload: request
      };
  }
  </code></pre>