如何使用Reactjs和Axios正确提出API请求?

时间:2019-08-17 01:28:46

标签: reactjs axios

我正在使用最新版本的 ReactJS ,并通过 Axios 发出请求。但是在进入draw()函数之前,我遇到了以下错误:

cancel()

因为问题出在组件被拆卸后立即泄漏了内存。但是现在取消请求后,我在控制台上收到以下消息:

enter image description here 我觉得这很奇怪,因为似乎系统出现了问题。

取消请求以避免内存泄漏的正确方法是什么?

组件:

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.
    in MenuPlaylist (at Sidebar/index.js:19)
    in aside (created by Context.Consumer)
    in StyledComponent (created by styled.aside)
    in styled.aside (at Sidebar/index.js:11)
    in Sidebar (at Search/index.js:16)
    in Search (created by Context.Consumer)

AXIOS:

import React, { Component } from "react";

// STYLES
import { Menu, Title } from "./styles";

// SERVICES
import { cancelAxiosRequest, getAllPlaylist } from "services/Api";

// SUBCOMPONENT'S
import { CreatePlaylist, CreatedPlaylist } from "components";

class MenuPlaylist extends Component {
  state = {
    data: []
  };

  // LIFE CYCLES
  componentDidMount() {
    this.consumeAPI();
  }

  componentWillUnmount() {
    cancelAxiosRequest("Request Canceled.");
  }

  // METHODS
  consumeAPI = () => {
    getAllPlaylist().then(({ data }) => {
      this.setState({ data: data });
    });
  };

  render = () => {
    return (
      <Menu>
        <Title>PLAYLISTS</Title>
        <CreatePlaylist />
        <CreatedPlaylist data={this.state.data} />
      </Menu>
    );
  };
}

export default MenuPlaylist;

2 个答案:

答案 0 :(得分:0)

根据documentation“取消”表示,诺言会针对您指定的消息引发“取消”错误。

要解决:

// ...

getAllPlaylist()
  .then(({ data }) => {
    this.setState({ data });
  })
  .catch(err => {
    if (axios.isCancel(err)) {
      return; // ignore
    }
    throw err; // or handle other errors
  });

// ...

尽管我觉得更改导出的值并不是使用取消令牌的最佳方法。首先检查是否需要卸载该组件,但如果有时确实只是要卸载该组件,则可以尝试类似

export function getAllPlaylist(cancelToken) {
  return instance.get("/playlist", {
    cancelToken: cancelToken
  });
}

// ...

getAllPlaylist(new CancelToken(c => this.cancel = c))
  .then(({ data }) => {
    this.setState({ data });
  });

// ...

componentWillUnmount() {
  this.cancel();
}

我不知道这是否100%理想,但这可以避免组件的多个实例争用单个变量。

答案 1 :(得分:0)

在鱼钩中,您应该做类似的事情

.catch((e) => {
        if (axios.isCancel(e)) return;
        setError(true);
      });

因为取消不是错误