首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用Reactjs和Axios正确地发出API请求?

如何使用Reactjs和Axios正确地发出API请求?
EN

Stack Overflow用户
提问于 2019-08-17 01:28:46
回答 2查看 223关注 0票数 0

我正在使用ReactJS的最新版本,并使用Axios进行请求。但是,在输入cancel()函数之前,我得到了以下错误:

代码语言:javascript
复制
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)

因为问题是,一旦组件拆卸,它就泄漏了内存。但是现在取消请求,我在控制台上得到以下消息:

我觉得很奇怪,因为这个系统似乎遇到了麻烦。

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

组件:

代码语言:javascript
复制
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;

AXIOS:

代码语言:javascript
复制
import axios from "axios";

const instance = axios.create({
  baseURL: "http://localhost:3001",
  timeout: 1000
});

let CancelToken = axios.CancelToken;
export let cancelAxiosRequest;

// GET'S
export function getNewReleases() {
  return instance.get("/newReleases");
}

export function getAllPlaylist() {
  return instance.get("/playlist", {
    cancelToken: new CancelToken(function executor(c) {
      cancelAxiosRequest = c;
    })
  });
}

export function getPlaylist(name) {
  return instance.get("/playlist", {
    params: {
      name: name
    }
  });
}

// POST'S
export function postNewPlaylist(id, name) {
  return instance.post("/playlist", {
    id: id,
    to: `/playlist/${id}`,
    name: name
  });
}
EN

回答 2

Stack Overflow用户

发布于 2019-08-17 07:59:57

根据文档,“取消”意味着承诺与您指定的消息一起抛出一个取消错误。

修复:

代码语言:javascript
复制
// ...

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

// ...

虽然我觉得更改导出的值并不是使用cancel令牌的最佳方式。首先检查是否需要卸载组件,但如果它确实只是有时要卸载的话,可以尝试如下

代码语言:javascript
复制
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%理想的,但这避免了组件为一个单一变量而斗争的多个实例。

票数 0
EN

Stack Overflow用户

发布于 2020-11-16 13:33:55

在抓到的时候,你应该做一些类似的事情

代码语言:javascript
复制
.catch((e) => {
        if (axios.isCancel(e)) return;
        setError(true);
      });

因为取消不是错误

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57532651

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档