事件触发两次反应无状态组件

时间:2018-05-15 04:51:07

标签: reactjs office-ui-fabric

我创建了两个组件,一个是Stateful(CurrentProjects),另一个是无状态(PopUpPanel)。在无状态组件中,我使用了Office UI Fabric反应组件Panel

Panel有一个属性OnDismiss,当单击面板上的关闭图标时会触发该属性。我通过CurrentProject组件将函数作为属性传递给PopUpPanel组件。但是,当我单击关闭图标时,CurrentProject组件上的函数将被触发两次。

所以我的问题是它为什么要两次调用它。我的代码如下

CurrentProjects组件

        import * as React from 'react';

    import {
    DocumentCard,
    DocumentCardActions,
    DocumentCardActivity,
    DocumentCardLocation,
    DocumentCardPreview,
    DocumentCardTitle,
    IDocumentCardPreviewProps,
    IDocumentCardActivityProps,
    Panel,
    PanelType,
    Image,
    Persona,
    IPersonaProps,
    PersonaSize
    } from 'office-ui-fabric-react';


    import styles from './CurrentProjects.module.scss';
    import { ICurrentProjectsProps } from './ICurrentProjectsProps';
    import { ICurrentProjectsState } from './ICurrentProjectsState';
    import { escape,  } from '@microsoft/sp-lodash-subset';
    import { ImageFit } from 'office-ui-fabric-react/lib/Image';
    import { TestImages } from "../../../../common/TestImages";
    import { IProject } from '../IProject';
    import PopUpPanel from "../PopUpPanel/PopUpPanel";
    import IPopUpPanelProps from "../PopUpPanel/IPopUpPanelProps";

    const img = require('../../../../images/avatar-kat.png');

    export default class CurrentProjects extends React.Component<ICurrentProjectsProps, ICurrentProjectsState> {

    public constructor(props:ICurrentProjectsProps){
        super(props);
        this.state = {
        showPanel:false,
        currentProject: null
        };

        this.onDismiss = this.onDismiss.bind(this);
    }

    private onCardClick(id:number, event:React.SyntheticEvent<HTMLElement>):void{
        //console.log("event=>",event.currentTarget);
        //console.log("Id=>",id);
        //debugger;
        this.setState((prevState:ICurrentProjectsState)=>{
        const project = this.props.projects.filter(proj=>proj.ID===id)[0];

        return {
            showPanel: !prevState.showPanel,
            currentProject: project
        };
        });
    }

    private onDismiss():void{
        //debugger;
        this.setState((prevState:ICurrentProjectsState)=> {
        return {
            showPanel: false //!prevState.showPanel
        };
        });
    }

    public render(): JSX.Element {

        const project:IProject = this.state.currentProject;

        const previewProps: IDocumentCardPreviewProps = {
        previewImages: [
            {
            name: 'My Project',
            previewImageSrc: TestImages.documentPreview,
            imageFit: ImageFit.contain,
            width: 250,
            height: 100
            },

        ],
        };

        const element:JSX.Element[] = this.props.projects === undefined ? []: this.props.projects.map((project,index) => {

        const style = {
            width: project.PercentageComplete + "%",
        };

        let dueDate: string = "";

        if(project.DueDate)
        {
            const dueDateObj = new Date(project.DueDate.toString());
            dueDate = dueDateObj.toLocaleDateString('en-gb',{year: '2-digit', month: 'short', day: 'numeric'});
        }

        return (
                <DocumentCard className={styles.myCard} key={project.ID} onClick={this.onCardClick.bind(this,project.ID)}>
                <div className={styles.priorityDiv + " " + styles[this.getProjectPriorityClassName(project.Priority)]}>
                    <DocumentCardPreview { ...previewProps } />
                    <div className={styles.projectDetails}>
                    <DocumentCardTitle
                        title={project.Client}
                        shouldTruncate={ false }
                        showAsSecondaryTitle={true}
                    />
                    <div className={styles.detailsDiv + ' ms-fontSize-mi'}><span className='ms-font-mi'>Title:</span> {project.Title}</div>
                    <div className={styles.detailsDiv + ' ms-fontSize-mi'}><span className='ms-font-mi'>BU:</span> {project.BusinessUnit}</div>
                    <div className={styles.detailsDiv + ' ms-fontSize-mi'}><span className='ms-font-mi'>Due Date:</span> {dueDate}</div>

                    <div className={styles.seperatorDiv}>
                        {/* <hr/> */}
                        <div className={styles.progressBarDiv}><div style={style}></div></div>
                        <span>{project.PercentageComplete}%</span>
                    </div>

                    <div className={styles.detailsDiv + ' ms-fontSize-mi'}>{project.RequestType}</div>
                    </div>
                </div>
                </DocumentCard>
            );
        });

        const popUpPanelProps:IPopUpPanelProps = {
        project: project,
        showPanel: this.state.showPanel,
        //onDismiss: this.onDismiss
        };

        return (
        <div className={styles.currentProjects}>
            {element}
            <PopUpPanel {...popUpPanelProps} onDismiss={this.onDismiss}  />
        </div>
        );
    }

    private getProjectPriorityClassName(priority:string): string {
        switch(priority)
        {
        case "Low" :
            return "priorityLow";

        case "Medium" :
        case "Moderate" :
            return "priorityMedium";

        case "High" :
            return "priorityHigh";

        default:
            return "";
        }
    }

    private getProgressBarColor(progress:number): string {
        if(progress <= 30) {
        return "red";
        } else if(progress >30 && progress <=70) {
        return "orange";
        } else if(progress >70) {
        return "green";
        }
    }

    }

PopUpPanel组件

        import * as React from 'react';

    import {
    Panel,
    PanelType,
    Image,
    Persona,
    IPersonaProps,
    PersonaSize
    } from 'office-ui-fabric-react';


    import styles from '../ProjectCardBoard/CurrentProjects.module.scss';
    import IPopUpPanelProps from './IPopUpPanelProps';
    import { escape,  } from '@microsoft/sp-lodash-subset';
    import { ImageFit } from 'office-ui-fabric-react/lib/Image';
    import { TestImages } from "../../../../common/TestImages";
    import { IProject } from '../IProject';

    const img = require('../../../../images/avatar-kat.png');

    const PopUpPanel: React.SFC<IPopUpPanelProps> = (props:IPopUpPanelProps) => {

        if(!props.project)
            return null;

        const project = props.project;

        // const onDismiss = ()=> {
        //     this.props.onDismiss();
        // };

        return (<Panel 
            isOpen={ props.showPanel }
            type={ PanelType.smallFluid }
            onDismiss={ props.onDismiss }>
            <div className={styles.ProjectDetailsPanel + " ms-Grid"}>
                <div className="ms-Grid-row">
                <div className="ms-Grid-col ms-md3 ms-lg2 ms-xl2 ms-xxl2 ms-xxxl1">
                    <Image src={String(img)}
                        imageFit={ImageFit.cover}
                        className={styles.ProjectIconDP}
                        alt='Some Alt' />
                </div>

                <div className="ms-Grid-col ms-md6 ms-lg8 ms-xl7 ms-xxl8 ms-xxxl9">
                    <p className="ms-fontSize-s ms-fontWeight-semibold">{project.Client}</p>
                    <p className="ms-fontSize-mi">{project.Title} <span className="ms-fontSize-s">  |  </span>  {project.BusinessUnit}  <span className="ms-fontSize-s">  |  </span>{project.RequestType}</p>
                </div>

                <div className="ms-Grid-col ms-md3 ms-lg2 ms-xl3 ms-xxl2 ms-xxxl2">
                    <p>Total Contract Value</p>
                    <p><strong>{project.TotalContractValue}</strong></p>
                </div>
                </div>

                <div className="ms-Grid-row">
                <div className="ms-Grid-col ms-sm12 ms-md12">
                    <h3>{"Bid Team".toUpperCase()}</h3>
                    <div className={styles.lineSeperator}></div>
                </div>
                </div>

                <div className="ms-Grid-row">
                <div className="ms-Grid-col ms-mdPush5 ms-md2 ms-lg2 ms-xl1 ms-textAlignCenter">
                    <div className={styles.peopleHeaderDiv}>
                    <h3 className={styles.peopleHeading}>{"Core Team".toUpperCase()}</h3>
                    </div> 
                    {project.CoreTeam && project.CoreTeam.map((member)=>{
                    const personaProps:IPersonaProps = {

                        imageUrl: member.ImgSrc,
                        imageInitials: member.Title.split(" ").reduce((prevVal,currentVal,index)=>{
                        return prevVal += currentVal.charAt(0);
                        },""),
                        primaryText: member.Title,
                        secondaryText: member.Designation,
                        tertiaryText: member.PhoneNo,
                        size:PersonaSize.size72
                    };

                    return <Persona {...personaProps} />;
                    })}
                    <div className={styles.peopleHeaderDiv}>
                    <h3 className={styles.peopleHeading}>{"Contributors".toUpperCase()}</h3>
                    </div>
                    {project.Contributors && project.Contributors.map((member)=>{
                    const personaProps:IPersonaProps = {

                        imageUrl: member.ImgSrc,
                        imageInitials: member.Title.split(" ").reduce((prevVal,currentVal,index)=>{
                        return prevVal += currentVal.charAt(0);
                        },""),
                        primaryText: member.Title,
                        secondaryText: member.Designation,
                        tertiaryText: member.PhoneNo,
                        size:PersonaSize.size72
                    };

                    return <Persona {...personaProps} />;
                    })}
                </div>
                </div>

                <div className="ms-Grid-row">
                <div className="ms-Grid-col ms-sm12 ms-md12">
                    <h3>{"Reason For Status".toUpperCase()}</h3>
                    <div className={styles.lineSeperator}></div>
                </div>
                </div>

                <div className="ms-Grid-row">
                <div className="ms-Grid-col ms-sm12 ms-md12"
                    dangerouslySetInnerHTML={{__html:project.ReasonForStatus}} />
                </div>

                <div className="ms-Grid-row">
                <div className="ms-Grid-col ms-sm12 ms-md12">
                    <h3>{"Win Strategy".toUpperCase()}</h3>
                    <div className={styles.lineSeperator}></div>
                </div>
                </div>

                <div className="ms-Grid-row">
                <div className="ms-Grid-col ms-sm12 ms-md12"
                    dangerouslySetInnerHTML={{__html:project.WinStrategy}} />
                </div>

                <div className="ms-Grid-row">
                <div className="ms-Grid-col ms-sm12 ms-md12">
                    <h3>{"Key Actions".toUpperCase()}</h3>
                    <div className={styles.lineSeperator}></div>
                </div>
                </div>

                <div className="ms-Grid-row">
                <div className="ms-Grid-col ms-sm12 ms-md12"
                    dangerouslySetInnerHTML={{__html:project.KeyActionsOrNextSteps}} />
                </div>

            </div>

    </Panel>);
    };

    export default PopUpPanel;

注意:如果我在PopupPanel组件中将行if(!props.project)更改为if(!props.project || !props.showPanel),则只触发一次事件。

0 个答案:

没有答案