【问题标题】:React componentDid mount get Async image. if not done before changing page, how to cancel the request?React componentDid mount 获取异步镜像。如果在更改页面之前没有完成,如何取消请求?
【发布时间】:2019-08-06 09:44:37
【问题描述】:

对于来自 Angular 背景的反应,我有点陌生。最近我正在构建一个页面,我在其中显示所有需要从 microsoft graph api 获取图像的卡片。调用的返回类型是 base64 字符串。我不想把它放到 redux 中,因为它会使我的 devtools 不可读。

因此,我决定使用 this.isMounted 模式 (Cancel All Subscriptions and Asyncs in the componentWillUnmount Method, how?) 在 componentDidMount 生命周期挂钩中进行异步调用。然而问题是,由于某种原因,这并没有取消订阅我所做的异步调用。我不确定我是否犯了错误或是否需要取消订阅而不是检查组件是否已安装。但我找不到有关如何处理此问题的任何信息。

任何帮助将不胜感激。

我的团队卡代码:

import React from "react";
import { Icon } from "office-ui-fabric-react/lib/Icon";
import TeamCardLogo from "./teamCardLogo/teamCardLogo";
import TeamCardPersona from "./teamCardPersona/teamCardPersona";
import { GetGroupMembers } from "../../HttpRepositories/graphRepository";
import { FormattedMessage } from "react-intl";
import Fade from "react-reveal/Fade";
import { Modal } from "office-ui-fabric-react/lib/Modal";
import reactAppInsights from "react-appinsights";
import TeamModal from "./teamModal/teamModal";

类 TeamCard 扩展 React.Component {

    state = {
        members: "",
        modelIsOpen: false
    };

    async componentDidMount() {
        let members = await GetGroupMembers(this.props.id);

        if (this.state.member !== "error") {
            this.setState({ members });
        }
    }

    _openModal = id => {
        this.setState({ modelIsOpen: true });
    };

    _closeModal = () => {
        this.setState({ modelIsOpen: false });
    };

    render() {
        let members = "";

        if (
            typeof this.state.members !== "undefined" &&
            this.state.members.length > 0 &&
            this.state.members !== "error"
        ) {
            members = this.state.members.map((member, i) => {
                if (i < 5) {
                    return (
                        <div className="team-card-body__personas-wrapper-person" key={i}>
                            <TeamCardPersona
                                className="team-card-body__personas-wrapper-person"
                                member={member}
                                key={i}
                            />
                        </div>
                    );
                }
            });
        } else {
            members = <div className="no-members-spacer" />;
        }
        let favouriteIcon = "";

        this.props.isFavorite === true
            ? (favouriteIcon = <Icon iconName="FavoriteStarFill" />)
            : (favouriteIcon = <Icon iconName="FavoriteStar" />);

        return (
            <React.Fragment>
                {/* <Fade bottom delay={this.props.delay} appear={true}> */}
                <article
                    className="team-card-wrapper"
                    onClick={() => this._openModal(this.props.id)}
                >
                    <header className="team-card-wrapper__header">
                        <TeamCardLogo
                            injectClass="team-card-wrapper__header-photo"
                            teamId={this.props.id}
                        />
                        <div className="team-card-wrapper__header-options-wrapper">
                            <div className="header-options__icon-group">
                                <div className="header-options__group-type">
                                    <Icon iconName="LockSolid" />
                                </div>
                            </div>

                            <div className="header-options__icon-group">
                                <div className="header-options__favourite">{favouriteIcon}</div>
                            </div>
                        </div>
                    </header>

                    <section className="team-card-body">
                        <h1>{this.props.title}</h1>
                        <h2>
                            {" "}
                            <FormattedMessage
                                id="teamcard.memberCount"
                                defaultMessage="Leden"
                            />
                            :{this.state.members.length}
                        </h2>

                        <div className="team-card-body__personas-wrapper">{members}</div>

                        <p className="description">{this.props.description}</p>

                        {/* <div className="team-card-body__join-button-wrapper">
                            <PrimaryButton text="Lid worden" />
                        </div> */}
                    </section>
                </article>
                {/* </Fade> */}
                <Modal
                    titleAriaId={this._titleId}
                    subtitleAriaId={this._subtitleId}
                    isOpen={this.state.modelIsOpen}
                    onDismiss={this._closeModal}
                    isBlocking={false}
                    containerClassName="team-modal-wrapper"
                >
                    <TeamModal
                        teamId={this.props.id}
                        title={this.props.title}
                        description={this.props.description}
                        favorite={this.props.isFavorite}
                        members={this.state.members}
                        closeModal={this._closeModal}
                    />
                </Modal>
            </React.Fragment>
        );
    }
}

export default TeamCard;

我的 TeamCardLogo 代码(进行异步调用)

import React from "react";
import { Icon } from "office-ui-fabric-react/lib/Icon";
import { getImage } from "../../../HttpRepositories/graphRepository";

class TeamCardImage extends React.Component {
    constructor(props) {
        super(props);
        this._isMounted = false;
    }

    state = {
        groupImage: ""
    };

    getLogo = () => {};

    async componentDidMount() {
        this._isMounted = true;

        if (this._isMounted) {
            let logo = await getImage(
                `https://graph.microsoft.com/v1.0/groups/${
                    this.props.teamId
                }/photo/$value`
            );

            if (logo !== "error") {
                this.setState({ groupImage: logo });
            }
        }
    }

    render() {
        let injectedClassName =
            this.props.injectClass != "" ? this.props.injectClass : "";
        let headerPhoto = "";
        const groupIcon = (
            <div className="team-card-wrapper__header-photo-alt">
                <Icon iconName="Group" />
            </div>
        );
        if (this.state.groupImage === "") {
            headerPhoto = groupIcon;
        } else {
            headerPhoto = <img src={this.state.groupImage} alt=" " />;
        }

        return (
            <React.Fragment>
                <div className={injectedClassName}>{headerPhoto}</div>
            </React.Fragment>
        );
    }

    componentWillUnmount() {
        this._isMounted = false;
    }
}

export default TeamCardImage;

我的 httpRepos 代码

import { getGraphToken } from "../adalConfig";
import axios from "axios";

export const GetGroupMembers = async groupId => {
    // we initiate a new token, to be sure that it didn't expire.
    let graphToken = getGraphToken();

    try {
        let response = await axios({
            url: `https://graph.microsoft.com/v1.0/groups/${groupId}/members?$select=id,displayName`,
            method: "GET",
            headers: { Authorization: "Bearer " + graphToken }
        });

        if (response.status != 200 && response.status != 204) {
            return "error";
        }

        return await response.data.value;
    } catch (error) {
        return "error";
    }
};

    export const getImage = async url => {
        // we initiate a new token, to be sure that it didn't expire.
        let graphToken = getGraphToken();

        try {
            let response = await axios({
                url: url,
                method: "get",
                responseType: "blob",
                headers: { Authorization: "Bearer " + graphToken }
            });

            if (response.status != 200 && response.status != 204) {
                return "error";
            }

            var urlCreator = window.URL || window.webkitURL;
            var imageUrl = urlCreator.createObjectURL(response.data);

            return await imageUrl;
        } catch (error) {
            return "error";
        }
    };

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    您想在调用setState 之前检查_isMounted 是否仍然是true,而不是在开始请求之前。

    async componentDidMount() {
      this._isMounted = true;
    
      let logo = await getImage(
        `https://graph.microsoft.com/v1.0/groups/${this.props.teamId}/photo/$value`
      );
    
      if (this._isMounted && logo !== "error") {
        this.setState({ groupImage: logo });
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-03-07
      • 1970-01-01
      • 2021-02-06
      • 1970-01-01
      • 2022-11-03
      • 1970-01-01
      • 2020-02-06
      • 2021-01-11
      • 2015-09-24
      相关资源
      最近更新 更多