嵌套的删除功能导致未定义的错误

时间:2019-04-14 07:20:13

标签: javascript reactjs

我有2个组件1 /父级---->将删除功能传递给子Component,但它导致未定义

TypeError: Cannot read property 'onHandleDelete' of undefined

我尝试了所有可反应文档提供的功能,但对我没有任何帮助 父组件

import React from 'react';
import PropTypes from 'prop-types';
import get from 'lodash/get';
// import isEmpty from 'lodash/isEmpty';
import { connect } from 'react-redux';
import isObject from 'lodash/isObject';
import classnames from 'classnames';
import moment from 'moment-hijri';
import uuid from 'uuid';

// Material-UI
import { withStyles } from '@material-ui/core/styles';
import Grid from '@material-ui/core/Grid';
import Paper from '@material-ui/core/Paper';
import Typography from '@material-ui/core/Typography';

// components
import Actions from './Actions';
import Supervisor from './Supervisor';

// Forms
import Entity from '~/Components/Entity';
import { BaseFormComponent, Form, FormBreak, FormDivider, FormContainer, FormItem } from '~/Components/FormComponent';
import { LabelAndValue } from '~/Components/FormComponent/Controls';
import { 
  isRequired,
  noEnglish,
  isObjectRequired,
} from '~/Services/Validators';

// Redux
import OfficesActions from '~/Redux/Actions/Offices';

import { VisitStatus } from '~/Services/StaticLookups';
import Strings from '~/Services/Strings';
import Notifications from '~/Services/Notifications';
import Message from '~/Components/Message';
import Navigate from '~/Services/Navigate';

import styles from './styles';

@withStyles(styles)
class AssignmentsEditorScreen extends BaseFormComponent {
  constructor(props) {
    super(props);

    this.initState({ 
      supervisors: [],
      insititution: [],
      inistitutionsLookup: [], 
      selectedSupervisors: [],
      previousSupervisorsFromId: [],
      plannedVisitInfoFromId: {},
      institutionDetails: {},
      account: {},
      error: false,

      form: {
        id: {
          type: this.types.string,
          value: 0,
        },
        institutionId: {
          type: this.types.number,
          validators: [ isRequired() ],
        },
        visitTypeId: {
          type: this.types.number,
          validators: [ isRequired() ],
        },
        startDate: {
          type: this.types.object,
          validators: [ isObjectRequired() ]
        },
        endDate: {
          type: this.types.object,
          validators: [ isObjectRequired() ]
        },
        office: {
          type: this.types.string,
          UIOnly: true
        },
        plannedVisitSupervisors: {
          type: this.types.string,
          UIOnly: true
        },
        visitStatus: {
          type: this.types.string,
          UIOnly: true
        },
        reason: {
          type: this.types.string,
          validators: [ noEnglish() ],
        },
      },
    });
  }

  componentDidMount() {
    super.componentDidMount();

    const id = get(this, 'props.match.params.id', null);
    const { offices, account } = this.props;

    this.searchableEntity.get();

    if (id) {   
      this.addFormFields({
        referenceNumber: {
          type: this.types.string,
          UIOnly: true
        },
      });  

      this.entity.get({ id });

    } else {
      this.removeFormFields([ 'referenceNumber' ]);    
    }

    if (!offices.isSet) {
      this.props.getOffices();
    }

    this.setState({ account });

  }

  componentDidUpdate(prevProps) {
    if(this.state.account !== this.props.account) {
      const employeeOfficeId = this.props.account.myRoles.find(item => item.roleName === 'PTSupervisionEmployees').officeId;
      // // To Switch to employee Office Once he Opens The Editor
      this.handleOfficesChange(employeeOfficeId);
      this.setFieldValue('office', employeeOfficeId);
      this.setState({ account: this.props.account });
    }

  }

  onSubmit() {
    const id = get(this, 'props.match.params.id', null);
    const { selectedSupervisors, previousSupervisorsFromId } = this.state;
    let plannedVisitors = [];

    if(selectedSupervisors.length > 0) {
      selectedSupervisors.map(item => {
        plannedVisitors.push({ supervisorName: item.name });
      });
    } else {
      plannedVisitors = [];
    }
    // To Append The Previous Supervisors with the newest supervisors
    if(previousSupervisorsFromId.length > 0) {
      previousSupervisorsFromId.map(item => {
        plannedVisitors.push({ supervisorName: item.supervisorName });
      });
    }

    if (this.isFormValid) {
      this.entity.post({
        ...this.formValues,
        plannedVisitSupervisors: [ ...plannedVisitors ],
        // to set id = 0 --> in create Mode || id Value in update Mode
        id: id ? id : 0 
      });
    } else {
      console.log('this', this.formValues,);
      this.showFormErrors();
    } 
  }

  onEntityPosted() {
    const id = get(this, 'props.match.params.id', null);

    if(id) {
      Notifications.notify('success', Strings.assignmentUpdatedSuccessfuly);
    } else {
      Notifications.notify('success', Strings.assignmentSavedSuccessfully);
    }
    Navigate.go('/plannedvisits');
  }

  onEntityPostedError(data) {
    if(data === 'Failed to create visit!, another visit is on for the institution!') {
      Notifications.notify('error', Strings.duplicatPlannedVisits);
      this.setState({ error: true });
    }
  }

  onEntityReceived(data) {
    const previousSupervisorsFromId = [ ...data.plannedVisitSupervisors ];
    const plannedVisitInfoFromId = { ...data };    

    if(isObject(data)) {
      this.updateFormValues(data, () => {
        if(data.hasOwnProperty('visitReasonId')) {
          this.addFormFields({
            visitReasonId: {
              type: this.types.number,
              validators: [ isRequired() ],
              value: data.visitReasonId,
            }
          });
        }
      });
    }
    this.setState({ 
      previousSupervisorsFromId,
      plannedVisitInfoFromId
    });
  }

  onSearchableEntityReceived(data) {
    if(data && data.licensingInstitutionsModel) {
      const insititution = [ ...data.licensingInstitutionsModel ];

      if (data.licensingInstitutionsModel && data.licensingInstitutionsModel.length > 0) {
        {
          data.licensingInstitutionsModel.map(item => {
            this.setState(prevState => ({ 
              inistitutionsLookup: prevState.inistitutionsLookup.concat({
                id: item.institutionId,
                nameAr: item.fullName
              }),
              insititution 
            }));
          });
        }
      }
    }
  }

  onSupervisorsByOfficeEntityReceived(data) {
    this.setState({ supervisors: data.result });
  }

  handleOfficesChange(officeId) {
    this.supervisorsByOfficeEntity.get({ officeId });
  }

  onHandleDelete(member) {

    console.log('member', member);
  }

  x(m) {
    console.log('member');
  }

  handleReasonField(id) {
    if(id === 1) {
      this.addFormFields({
        visitReasonId: {
          type: this.types.string,
          validators: [ isRequired() ]
        },
      });
    } else {
      this.removeFormFields([ 'visitReasonId' ]);
    }
  }

  getInstitutionValues(institutionId) {
    const { insititution } = this.state;

    if(insititution && insititution.length > 0) {
      const institutionDetails = insititution.filter(item => item.institutionId === institutionId);

      this.setState({ institutionDetails });
    }
  }

  handleAddMember(value) {
    const member = this.state.supervisors.find(item => item.name === value);

    if(member) {
      // in order not to allow add multiple supervisors withe the same name
      const isInPreviousSupervisors = this.state.previousSupervisorsFromId.find(item => item.supervisorName === member.name);

      if(!isInPreviousSupervisors) {
        const selectedSupervisors = [ ...this.state.selectedSupervisors ];
        selectedSupervisors.push(member);

        this.setState({ selectedSupervisors });
      } else {
        Notifications.notify('error', `${member.displayName} ${Strings.userAlreadyInTheList} ${member.name}`);
      }
    }
  }

  get offices() {
    const { offices } = this.props;

    if(offices.list.length >= 1) {
      const lookup = {};

      offices.list.forEach(item => {
        lookup[item.id] = item.name;
      });

      return lookup;
    }

    return {};
  }

  get plannedVisitsSupervisors() {
    const lookup = {};

    this.state.supervisors.forEach(item => {
      const isSelectedBefore = this.state.selectedSupervisors.find(sItem => sItem.name === item.name);

      if(!isSelectedBefore) {
        lookup[item.name] = item.displayName;
      }
    });
    return lookup;
  }

  get getSupervisors() {
    const { selectedSupervisors, previousSupervisorsFromId } = this.state;

    return selectedSupervisors.concat(previousSupervisorsFromId);
  }

  render() {
    // const { form, inistitutions, supervisorsByOffice, previousSupervisorsFromId } = this.state;
    const { form, error, inistitutionsLookup, plannedVisitInfoFromId } = this.state;
    const { classes } = this.props;
    const id = get(this, 'props.match.params.id', null);
    const inistitutionsCheck = inistitutionsLookup && inistitutionsLookup.length === 0;
    // const supervisorsCheck = supervisorsByOffice && supervisorsByOffice.length === 0;
    const disabled = plannedVisitInfoFromId && plannedVisitInfoFromId.plannedVisitActions && !plannedVisitInfoFromId.plannedVisitActions.allowEdit;

    const {
      TextField,
      LookupSelectField,
      StaticLookupSelectField,
      SelectAutocompleteField,
      Date2Field,
    } = this;

    return (
      <React.Fragment>
        <Entity
          storeId={'Supervision-PlannedVisit-Editor'}
          entityRef={ref => { this.entity = ref; }}
          onEntityReceived={data => this.onEntityReceived(data)}
          onEntityPosted={data => this.onEntityPosted(data)}
          onEntityPostedError={data => this.onEntityPostedError(data)}
          render={store => (
            <Form loading={store.loading}>
              <Grid container spacing={24}>
                <If condition={error}>
                  <Grid item xs={12}>
                    <Message variant={'error'} text={Strings.duplicatPlannedVisits} />
                  </Grid>
                </If>
                <Grid item xs={9}>

                  <Paper elevation={1} className={classes.box1}>
                    <fieldset className={classes.fieldSet}>
                      <legend>{Strings.assignmentDetails}</legend> 
                      <FormContainer>

                        <FormItem lg={6}>
                          <div className={classnames(classes.placeholder, id || inistitutionsCheck ? classes.disabledField : {})}>
                            <SelectAutocompleteField
                              name={'institutionId'}
                              label={Strings.assignmentInstitutionName}
                              emptyString={Strings.searchByNameAndLicense}
                              disabled={id || inistitutionsCheck}
                              data={inistitutionsLookup}
                              onChange={field => this.getInstitutionValues(field.value)}
                              // onSearch={e => console.log('e', e)}
                            />
                          </div>
                        </FormItem>

                        <FormItem lg={form.visitTypeId.value === 1 ? 3 : 6}>
                          <LookupSelectField
                            name={'visitTypeId'}
                            label={Strings.assignmentvisitType}
                            lookup={'VisitType'}
                            onChange={field => this.handleReasonField(field.value)}
                            disabled={disabled}
                          />
                        </FormItem>

                        <If condition={form.visitTypeId.value === 1 && form.visitReasonId}>
                          <FormItem lg={3}>
                            <LookupSelectField
                              name={'visitReasonId'}
                              label={Strings.assignmentvisitReason}
                              lookup={'VisitReason'}
                              disabled={disabled}
                            />
                          </FormItem>
                        </If>

                        <FormItem lg={6}>
                          <Choose>
                            <When condition={disabled}>
                              <LabelAndValue  
                                label={Strings.assignmentvisitStartDate}
                                value={plannedVisitInfoFromId.startDate.hijriDate}
                              />
                            </When>
                            <Otherwise>
                              <Date2Field
                                name={'startDate'}
                                label={Strings.assignmentvisitStartDate}
                                minDate={[
                                  moment().iYear(),
                                  moment().iMonth() + 1,
                                  moment().iDate()
                                ]}
                              />
                            </Otherwise>
                          </Choose>

                        </FormItem>

                        <FormItem lg={6}>
                          <Choose>
                            <When condition={disabled}>
                              <LabelAndValue  
                                label={Strings.assignmentvisitEndDate}
                                value={plannedVisitInfoFromId.endDate.hijriDate}
                              />
                            </When>
                            <Otherwise>
                              <Date2Field
                                name={'endDate'}
                                label={Strings.assignmentvisitEndDate}
                                minDate={[
                                  moment().iYear(),
                                  moment().iMonth() + 1,
                                  moment().iDate()
                                ]}
                              />
                            </Otherwise>
                          </Choose>
                        </FormItem>
                      </FormContainer>
                    </fieldset>
                  </Paper>

                  <Paper elevation={1} className={classes.box}>
                    <fieldset className={classes.fieldSet}>
                      <legend>
                        <Choose>
                          <When condition={disabled}>
                            {Strings.assignedSupervisors}
                          </When>
                          <Otherwise>
                            {Strings.addSupervisors}
                          </Otherwise>
                        </Choose>
                      </legend> 
                      <FormContainer className={classes.supervisorsContainer}>
                        <If condition={!disabled}>
                          <FormItem>
                            <div className={ classes.lookup }>
                              <StaticLookupSelectField
                                name= {'office'}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
                                label={Strings.office}                                                                                                                                                                                                                                
                                lookup= {this.offices}
                                onChange={field => this.handleOfficesChange(field.value)} 
                              />
                            </div>
                          </FormItem>

                          <FormItem>  
                            <StaticLookupSelectField 
                              name={'plannedVisitSupervisors'}
                              label={Strings.supervisorListName}
                              lookup={this.plannedVisitsSupervisors}
                              onChange={field => this.handleAddMember(field.value)}
                            />
                          </FormItem>
                        </If>

                        <If condition={this.getSupervisors.length > 0}>
                          <If condition={!disabled}>
                            <FormBreak />
                            <FormDivider />
                            <Typography variant='subtitle1' className={classes.supervisorsHeader}>
                              {Strings.assignedSupervisors}
                            </Typography>
                          </If>
                          <FormContainer className={classes.supervisorsContainer}>
                            <For each='member' of={this.getSupervisors} index='i'>
                              <FormItem lg={4} key={`${i}_${uuid()}`}>
                                <Supervisor 
                                  data={member}
                                  onHandleDelete={data => this.onHandleDelete(data)}
                                  disabled={disabled}
                                />
                              </FormItem>
                            </For>
                          </FormContainer>
                        </If>

                      </FormContainer>
                    </fieldset>
                  </Paper>

                  <Paper elevation={1} className={classes.box}>
                    <FormItem fullWidth>
                      <TextField
                        multiline
                        name={'reason'}
                        label={Strings.assignmentvisitreason}
                        disabled={disabled}
                      />
                    </FormItem>
                  </Paper>
                </Grid>
                <Grid item xs={3}>
                  {/* =========== Sidebar ============= */}
                  <If condition={form && form.visitStatus}>
                    <Paper elevation={1} className={classes.box}>
                      {/* lookup is Needed */}
                      <FormItem fullWidth>
                        <StaticLookupSelectField
                          name={'visitStatus'}
                          label={Strings.assignmentvisitStatus}
                          lookup={VisitStatus}
                          disabled
                        />
                      </FormItem>
                    </Paper>
                  </If>

                  <If condition={form && form.referenceNumber}>
                    <Paper elevation={1} className={classes.box}>
                      <FormItem fullWidth>
                        <TextField
                          name={'referenceNumber'}
                          label={Strings.violationReferenceNumber}
                          disabled
                        />
                      </FormItem>
                    </Paper>
                  </If>

                  <Paper elevation={1} className={classes.box}>
                    <FormItem fullWidth style={{ marginBottom: 10 }}>
                      <Actions disabled={disabled} onSubmit={() => this.onSubmit()} />
                    </FormItem>
                  </Paper>
                </Grid>
              </Grid>
            </Form>
          )}
        />
        {/* To get all institutions */}
        <Entity 
          storeId={'Supervision-Assignment-Searchable-Institution'}
          entityRef={ref => { this.searchableEntity = ref;}}
          onEntityReceived={data => this.onSearchableEntityReceived(data)}
        />
        {/* To get supervisors by office */}
        <Entity 
          storeId={'Supervision-Assignment-Supervisors-By-Office'}
          entityRef={ref => { this.supervisorsByOfficeEntity = ref;}}
          onEntityReceived={data => this.onSupervisorsByOfficeEntityReceived(data)}
        />
      </React.Fragment>
    );
  }
}

AssignmentsEditorScreen.propTypes = {
  classes: PropTypes.object,
  offices: PropTypes.object,
  account: PropTypes.object,
  getOffices: PropTypes.func
};

const mapStateToProps = store => ({
  offices: store.offices,
  account: store.account.data || {}
});

const mapDispatchToProps = dispatch => ({
  getOffices: () => dispatch(OfficesActions.get()),
});

AssignmentsEditorScreen.propTypes = {
  classes: PropTypes.object,
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(AssignmentsEditorScreen);

子组件

import React, { Component } from 'react';
import PropTypes from 'prop-types';

import { withStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import Paper from '@material-ui/core/Paper';
import Icon from '@material-ui/core/Icon';
import IconButton from '@material-ui/core/IconButton';
import DeleteIcon from '@material-ui/icons/Delete';
import Tooltip from '@material-ui/core/Tooltip';

import strings from '~/Services/Strings';
import { supervisor } from './styles';

@withStyles(supervisor)
class Supervisor extends Component {
  render() {
    const { classes, data, disabled } = this.props;
    console.log('da', data);
    return (
      <Paper className={classes.memberItem}>
        <If condition={!disabled}>
          <Tooltip title={strings.delete}>
            <IconButton className={classes.delete} onClick={() => this.props.onHandleDelete(data)}>
              <DeleteIcon />
            </IconButton>
          </Tooltip>
        </If>

        <div className={classes.memberIconWrapper}>
          <Icon className={classes.memberIcon}>person</Icon>
        </div>

        <div className={classes.memberDetails}>
          <div className={classes.subInfo}>
            <Typography gutterBottom className={classes.memberJobTitle} variant='subtitle1'>
              {strings.supervisorNameSub}
            </Typography>

            <Typography className={classes.memberName} variant='subtitle2'>
              <Choose>
                <When condition={data.displayName}>
                  {data.displayName}
                </When>
                <Otherwise>
                  <Choose>
                    <When condition={data.name}>
                      {data.name}
                    </When>
                    <Otherwise>
                      <Choose>
                        <When condition={data.supervisorName}>
                          {data.supervisorName}
                        </When>
                        <Otherwise>
                          {strings.emptyString}
                        </Otherwise>
                      </Choose>
                    </Otherwise>
                  </Choose>
                </Otherwise>
              </Choose>
            </Typography>
          </div>

          <div className={classes.subInfo}>
            <Typography gutterBottom className={classes.memberJobTitle} variant='subtitle1'>
              {strings.assignedVisitCountSub}
            </Typography>

            <Typography className={classes.memberName} variant='subtitle2'>
              <Choose>
                <When condition={typeof(data.assignedVisitCount) === 'number'}>
                  {data.assignedVisitCount}
                </When>
                <Otherwise>
                  {strings.emptyString}
                </Otherwise>
              </Choose>
            </Typography>
          </div>

          <div className={classes.subInfo}>
            <Typography gutterBottom className={classes.memberJobTitle} variant='subtitle1'>
              {strings.requiredVisitsCountPerMonthSub}
            </Typography>

            <Typography className={classes.memberName} variant='subtitle2'>
              <Choose>
                <When condition={typeof(data.requiredVisitsCountPerMonth) === 'number'}>
                  {data.requiredVisitsCountPerMonth}
                </When>
                <Otherwise>
                  {strings.emptyString}
                </Otherwise>
              </Choose>
            </Typography>
          </div>
        </div>
      </Paper>
    );
  }
}

Supervisor.propTypes = {
  classes: PropTypes.object,
  data: PropTypes.object,
  disabled: PropTypes.bool,

  key: PropTypes.string,
  onHandleDelete: PropTypes.func,
};

export default Supervisor;

这是我的父组件

<For each='member' of={this.getSupervisors} index='i'>
  <FormItem lg={4} key={`${i}_${uuid()}`}>
    <Supervisor 
      data={member}
      onHandleDelete={data => this.onHandleDelete(data)}
      disabled={disabled}
     />
   </FormItem>
</For>

这是onHandleDelete函数

  onHandleDelete(data) {

    console.log('member');
  }

这是我的子组件(主管)

<If condition={!disabled}>
 <Tooltip title={strings.delete}>
   <IconButton className={classes.delete} onClick={() => this.props.onHandleDelete(data)}>
      <DeleteIcon />
    </IconButton>
  </Tooltip>
</If>

这是来自控制台的错误

Uncaught TypeError: Cannot read property 'onHandleDeletion' of undefined
    at Object.onHandleDeletion (index.js:497)
    at onClick (Supervisor.js:24)
    at HTMLUnknownElement.callCallback (react-dom.development.js:100)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:138)
    at Object.invokeGuardedCallback (react-dom.development.js:187)
    at Object.invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:201)
    at executeDispatch (react-dom.development.js:461)
    at executeDispatchesInOrder (react-dom.development.js:483)
    at executeDispatchesAndRelease (react-dom.development.js:581)
    at executeDispatchesAndReleaseTopLevel (react-dom.development.js:592)
    at forEachAccumulated (react-dom.development.js:562)
    at runEventsInBatch (react-dom.development.js:723)
    at runExtractedEventsInBatch (react-dom.development.js:732)
    at handleTopLevel (react-dom.development.js:4476)
    at batchedUpdates$1 (react-dom.development.js:16659)
    at batchedUpdates (react-dom.development.js:2131)
    at dispatchEvent (react-dom.development.js:4555)
    at interactiveUpdates$1 (react-dom.development.js:16714)
    at interactiveUpdates (react-dom.development.js:2150)
    at dispatchInteractiveEvent (react-dom.development.js:4532)

其中data是肯定可以携带数据的对象

我希望在控制台中记录数据

0 个答案:

没有答案