Cancel Fetch Using Componentwillunmount in React JS

Asked

Viewed 75 times

0

Good evening. I’m having doubts about such a life cycle method of React and I’m doing tests. One of them is to cancel a request fetch, however, I’m not getting it. The console log. appears, but the request cancellation does not work. In my application, when clicking the button, there is a change of components and a request occurs. Here is my code:

const abortController = new AbortController()

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      load: true
    };
  }

  toogle = () => {
    const { load } = this.state;

    this.setState({ load: !load });
  };

  render(){
    const { load } = this.state
    return(
      <>
        {
          load?
          <>
            <h1>Principal</h1>
            <button onClick={this.toogle}>Clique</button>
          </>:
          <Teste click={this.toogle}/>
        }
      </>
    )
  }
}

class Teste extends Component {
  constructor(props) {
    super(props);
  }

  componentDidMount() {
    console.log("fui montado");

    fetch('https://pokeapi.co/api/v2/evolution-chain/?limit=6&offset=0',{
      signal: abortController.signal
    }).then(res => res.json()).then(res => console.log(res))
  }

  componentWillUnmount() {
    console.log("fui desmontado");
    abortController.abort()
  }

  render(){
    return(
      <>
        <h1>Requisição</h1>
        <button onClick={this.props.click}>Clique</button>
      </>
    )
  }
}

Does anyone have any idea what might be going on?

Thanks for your attention!

  • 1

    You may have to create that variable inside the component?

  • @Thalesmaia, I think the complexity you will introduce just to cancel the AJAX request is not worth it (in this type of request). Wouldn’t it be better if you just stopped the setState after the request if the component is unmounted?

  • Yes, but I read an article on React’s own website that says it’s considered anti-Pattern. And also in the documentation itself it says that one should cancel the request in Componentwillunmount, or is not a rule for all cases?

1 answer

0


The problem is that the request is a promise that is not cancellable. There is no specific reference to your request that cancels the promise you made above.

One way to do this would be to declare the request promisse in a variable...and then cancel using a method of that variable.

For example:

const makeCancelable = (promise) => {
    let hasCanceled_ = false;

    const wrappedPromise = new Promise((resolve, reject) => {
        promise.then(
            val => hasCanceled_ ? reject({isCanceled: true}) : resolve(val),
            error => hasCanceled_ ? reject({isCanceled: true}) : reject(error)
        );
    });

    return {
        promise: wrappedPromise,
        cancel() {
            hasCanceled_ = true;
        },
    };
};

const cancelablePromise = makeCancelable(fetch('LINK HERE'));

constructor(props){
    super(props);
    this.state = {
        isLoading: true,
        dataSource: [{
            name: 'loading...',
            id: 'loading',
        }]
    }
}

componentDidMount(){
    cancelablePromise.
        .then((response) => response.json())
        .then((responseJson) => {
            this.setState({
                isLoading: false,
                dataSource: responseJson,
            }, () => {

            });
        })
        .catch((error) =>{
            console.error(error);
        });
}

componentWillUnmount() {
    cancelablePromise.cancel();
}

But this approach has a lot of random code (Boilerplate) and is very verbose.

A recommendation would be to try to use Hooks. With Hooks the timing approach of requests made or cancelled is in relation to properties.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.