Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to cancel previous axios with redux in react

i have the following action in my action file.

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&page=`+page+`&size=`+size+`&where=`+JSON.stringify(where)+`&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&where=`+JSON.stringify(where), {cancelToken: source.token});  
    return {
        type: FETCH_WORKERJOBS_COUNT,
        payload: request
    };
}

How can i access the cancel token to cancel when I am importing the function into my component

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)=>{
            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 > 0){
              if($(".react-bs-table-tool-bar .react-bs-table-sizePerPage-dropdown").length <= 0){

                  $(".react-bs-table-sizePerPage-dropdown").prependTo(".react-bs-table-tool-bar");
              }
          }
      });
    }

    renderTable(services) {

        return (
            <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"
            >
                <TableHeaderColumn dataField="worker_job_id" dataSort={true} width={`60px`}>
                    #
                </TableHeaderColumn>
                <TableHeaderColumn dataField="job" filter={ { type: 'SelectFilter', options: jobType } }>Job</TableHeaderColumn>
                <TableHeaderColumn dataField="filename">Filename</TableHeaderColumn>
                <TableHeaderColumn
                    dataField="flag"
                    filter={{ type: 'TextFilter', defaultValue: 'C' }}
                    width={`60px`}
                >
                    Flag
                </TableHeaderColumn>
                <TableHeaderColumn dataField="total_time_taken" width={`125px`}>Total Time Taken</TableHeaderColumn>
                <TableHeaderColumn dataField="output" width={`100px`}>Analysis</TableHeaderColumn>
                <TableHeaderColumn dataField="ts_created">Created</TableHeaderColumn>
                <TableHeaderColumn dataField="ts_updated">Finished</TableHeaderColumn>     
                <TableHeaderColumn dataField="comms_matrix_id" width={`60px`}>#CM</TableHeaderColumn>
                <TableHeaderColumn dataField="visible_lines" width={`100px`}>Visible Lines</TableHeaderColumn>
                <TableHeaderColumn 
                    dataField="security_flows" 
                    width={`100px`} 
                    thStyle={{
                        whiteSpace: 'pre-wrap',
                        whiteSpace: '-moz-pre-wrap',
                        whiteSpace: '-pre-wrap',
                        whiteSpace: '-o-pre-wrap',
                        wordWrap: 'break-word'
                        }} 
                >
                    Security Flows
                </TableHeaderColumn>

            </BootstrapTable>
        );
    }

    render() {
        if(!this.runOnce && this.props.isReady){             
            this.runOnce = true;
            this.fetchWorkerJobs(this.options.page, this.options.sizePerPage, this.where, this.sort);
        }

        let table = <div>Loading...<i className="fa fa-spinner fa-spin"></i></div>;
        if ( Object.keys(this.props.reportsWorkerJobs).length > 0) {
            table = this.renderTable(this.state.data);
            this.moveElement();
        }

        return (
            <div className="container-fluid">
                <div className="row-fluid top-buffer">{table}</div>
            </div>
        );
    }
}

function mapStateToProps(state) {

    return {
        reportsWorkerJobs: state.reportsWorkerJobs,
        reportsWorkerJobsCount: state.reportsWorkerJobsCount
    };
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators(
        { fetchWorkerJobs, fetchWorkerJobsCount },
        dispatch
    );
}

export default connect(mapStateToProps, mapDispatchToProps)(WorkerJobs);

I want to cancel previous pagination requests etc.. I need to cancel

this.props.fetchWorkerJobsCount.cancel(); //not working
        this.props.fetchWorkerJobs.cancel(); //not working

I have tried to export the variable from action file and import into component but that does not work

actions.js

export const FETCH_WORKERJOBS_COUNT_CANCEL = wjc_cancel;

component

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

error i get is Uncaught TypeError: (0 , _actions.FETCH_WORKERJOBS_COUNT_CANCEL) is not a function

Update

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.

some not being cancelled fast enough

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&page=`+page+`&size=`+size+`&where=`+JSON.stringify(where)+`&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
    };
}
like image 668
shorif2000 Avatar asked Mar 12 '18 11:03

shorif2000


People also ask

How do I cancel a previous request in react?

Trigger the cancel request by calling source. cancel() where and when (in a react component this can be on the componentWillUnmount lifecycle method or on the click of a button) you need to cancel the request.

How do I terminate an Axios request?

You can also cancel a request using a CancelToken. The axios cancel token API is based on the withdrawn cancelable promises proposal. You can create a cancel token using the CancelToken.

How do I cancel Axios POST request in react?

To cancel or abort ajax requests in Axios in a React app, we can use the Axios cancel token feature. We define the answer state to store the request response. And we have the cancelTokenSource ref to store the cancellation token. In the request function, we set the cancelTokenSource.

How do I cancel Axios request in useEffect?

The source Contains The cancel Method, Which Can Be Invoked To Abort/cancel The Request. useEffect(() => { Const CancelToken = Axios. CancelToken; Const Source = CancelToken. source(); SetAxiosRes("axios Request Created"); GetReq(source).


2 Answers

Here is code that can be used:

// get info in component
useEffect(() => {
    const cancelToken = customAxios.CancelToken.source();
    dispatch(fetchStream(match.params.id, cancelToken.token));

    return () => {
        cancelToken.cancel(`Cancel fetchStream ${match.params.id}`)
    }
}, []);

// where fetchStream in store/actions/streams.js
export const fetchStream = (id, cancelToken) => async dispatch => {
    try {
        const {data: stream} = await axios.get(`/streams/${id}`, {
            cancelToken
        });

        dispatch({
            type: FETCH_STREAM,
            payload: stream
        })
    } catch (e) {
        console.log("fetchStream get error ", e);
    }
};
like image 195
Maxim Maximov Avatar answered Nov 01 '22 02:11

Maxim Maximov


You would need access to the source variable in order to cancel it.

Alternatively you could cancel the previous request when you create a new one (this seems to be your use case).

Something like the following (using the executor function syntax: https://github.com/axios/axios#cancellation so you get a new token for each request)

import axios from 'axios';
import $ from 'jquery';
var CancelToken = axios.CancelToken;
let wj_cancel, wjc_cancel;

export const FETCH_WORKERJOBS = 'fetch_workerjobs';

export function fetchWorkerJobs(page, size, where, sort) {
  wj_cancel && wj_cancel();
  const request = axios.get(`/api/user/report/comms/matrix/upload/format/json?quiet=1&page=` + page + `&size=` + size + `&where=` + JSON.stringify(where) + `&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
  };
}

export const FETCH_WORKERJOBS_COUNT = 'fetch_workerjobs_count';

export function fetchWorkerJobsCount(where) {
  wjc_cancel && wjc_cancel();
  const request = axios.get(`/api/user/report/comms/matrix/upload/count/format/json?quiet=1&where=` + JSON.stringify(where), {
    cancelToken: new CancelToken(function executor(c) {
        // An executor function receives a cancel function as a parameter
        wjc_cancel = c;
      }
  });
  return {
    type: FETCH_WORKERJOBS_COUNT,
    payload: request
  };
}
like image 40
Gabriele Petrioli Avatar answered Nov 01 '22 00:11

Gabriele Petrioli