Cancel a fetch request in react-native

15,092

Solution 1

the best solution is using rxjs observables + axios/fetch instead of promises, abort a request => unsubscribe an observable :

import Axios from "axios";
import {
    Observable
} from "rxjs";

export default class HomeScreen extends React.Component {
    subs = null;

    doStuff = () => {
        let observable$ = Observable.create(observer => {
            Axios.get('https://jsonplaceholder.typicode.com/todos', {}, {})
                .then(response => {
                    observer.next(response.data);
                    observer.complete();
                })
        });

        this.subs = observable$.subscribe({
            next: data => console.log('[data] => ', data),
            complete: data => console.log('[complete]'),
        });

    }

    cancel = () =>
        if (this.subs) this.subs.unsubscribe()

    componentWillUnmount() {
        if (this.subs) this.subs.unsubscribe();
    }

}

That is it :)

Solution 2

You don't need any polyfill anymore for abort a request in React Native 0.60 changelog

Here is a quick example from the doc of react-native:

/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 * @flow
*/

'use strict';

const React = require('react');
const {Alert, Button, View} = require('react-native');

class XHRExampleAbortController extends React.Component<{}, {}> {
  _timeout: any;

  _submit(abortDelay) {
    clearTimeout(this._timeout);
    // eslint-disable-next-line no-undef
    const abortController = new AbortController();
    fetch('https://facebook.github.io/react-native/', {
      signal: abortController.signal,
    })
      .then(res => res.text())
      .then(res => Alert.alert(res))
      .catch(err => Alert.alert(err.message));
    this._timeout = setTimeout(() => {
          abortController.abort();
    }, abortDelay);
  }

  componentWillUnmount() {
    clearTimeout(this._timeout);
  }

  render() {
    return (
      <View>
        <Button
          title="Abort before response"
          onPress={() => {
            this._submit(0);
          }}
        />
        <Button
          title="Abort after response"
          onPress={() => {
            this._submit(5000);
          }}
        />
      </View>
    );
  }
}

module.exports = XHRExampleAbortController;

Solution 3

I've written quite a bit actually about this subject. You can also find the first issue about the OLD lack of AbortController in React Native opened by me here

The support landed in RN 0.60.0 and you can find on my blog an article about this and another one that will give you a simple code to get you started on making abortable requests (and more) in React Native too. It also implements a little polyfill for non supporting envs (RN < 0.60 for example).

Share:
15,092
AHmedRef
Author by

AHmedRef

I'm a Multi-developper.

Updated on June 07, 2022

Comments

  • AHmedRef
    AHmedRef about 2 years

    Is there any way to abort a fetch request on react-native app ?

    class MyComponent extends React.Component {
      state = { data: null };
    
      componentDidMount = () =>
        fetch('http://www.example.com')
          .then(data => this.setState({ data }))
          .catch(error => {
            throw error; 
          });
    
      cancelRequest = () => {
       //???
      };
    
      render = () => <div>{this.state.data ? this.state.data : 'loading'}</div>;
    }
    

    i tried the abort function from AbortController class but it's not working !!

    ...
    abortController = new window.AbortController();
    
    cancelRequest =  () => this.abortController.abort();
    
    componentDidMount = () =>
            fetch('http://www.example.com', { signal: this.abortController.signal })
              ....
    

    Any help please !

  • AHmedRef
    AHmedRef about 5 years
    this is not working, i get this error message : Possible Unhandled Promise Rejection (id: 0): [AbortError: Aborted]
  • Nainal
    Nainal about 5 years
    From the docs:- This "polyfill" doesn't actually close the connection when the request is aborted, but it will call .catch() with err.name == 'AbortError' instead of .then()
  • hfossli
    hfossli over 4 years
    That does not cancel the underlying axios request. Just the subscription to the result.
  • mixdev
    mixdev over 2 years
    It's actually better to put the code here and additionally add a link to your article for more in-depth understanding.