无法读取未定义的 属性 'xxx.xxx'

Cannot read property 'xxx.xxx' of undefined

正在升级 meteor(从 1.4 到 1.7)和 react(从 15.3.2 到 16.8.6)。使用流星大气。

在处理删除指令的代码的一部分,控制台出现以下熟悉但毫无头绪的错误:

Uncaught TypeError: Cannot read property 'displayConfirmation' of undefined
    at remove (ticket.js:48)
    at onClick (list.jsx:180)
    at HTMLUnknownElement.callCallback (modules.js?hash=199fa8ade393a4d3c92b5b590836441c4936d1d6:54371)
    at Object.invokeGuardedCallbackDev (modules.js?hash=199fa8ade393a4d3c92b5b590836441c4936d1d6:54420)
    at invokeGuardedCallback (modules.js?hash=199fa8ade393a4d3c92b5b590836441c4936d1d6:54475)
    at invokeGuardedCallbackAndCatchFirstError (modules.js?hash=199fa8ade393a4d3c92b5b590836441c4936d1d6:54489)
    at executeDispatch (modules.js?hash=199fa8ade393a4d3c92b5b590836441c4936d1d6:54572)
    at executeDispatchesInOrder (modules.js?hash=199fa8ade393a4d3c92b5b590836441c4936d1d6:54597)
    at executeDispatchesAndRelease (modules.js?hash=199fa8ade393a4d3c92b5b590836441c4936d1d6:57461)
    at executeDispatchesAndReleaseTopLevel (modules.js?hash=199fa8ade393a4d3c92b5b590836441c4936d1d6:57470)

期望:删除前弹出确认对话框

部分代码如下:

components/list.jsx

...
onClick={() => actions.delete && remove()}><img src={require('/crm/images/icon_delete.png')}/> Delete all selected</span>
...

actions/ticket.js

import * as React from 'react';

import { push, goBack } from 'react-router-redux';
import { reset, SubmissionError } from 'redux-form';

import { notify, confirm } from '../../core/actions';

import {Tickets} from '../../../../lib/collections';

import {
  SELECT_TICKETS, UNSELECT_TICKETS, CHANGE_TICKETS_PAGE, SORT_TICKETS,

  LOAD_TICKET, UNLOAD_TICKET,
  LOAD_ACTIVITIES, UNLOAD_ACTIVITIES,

  CHANGE_CATEGORY, CHANGE_STATUS, CHANGE_DATE,
} from './actionTypes';

export default {
  remove(context) {
    const {Meteor, Store} = context;
    let tickets = Store.getState().tickets.list.selectedTickets;

    confirm.displayConfirmation(context, {        // <-- It can't seem to recognize this
      title: 'Removing Tickets',
      message: "<p>Are you sure you want to delete below tickets?<ul>{tickets.map((ticket, i) => <li key={'msg-' + i}>{ticket.ticketNo}</li>)}</ul></p>",
      callback: () => {
        Meteor.call('tickets.delete', tickets.map(ticket => ticket._id), (err) => {
          if (err) {
            return;
          }

          notify.sendNotify(context, `${tickets.map(ticket => ticket.ticketNo).join(', ')} ${tickets.length > 1 ? 'have' : 'has'} been deleted.`);
          unselect(context);
        });

      }
    });
  },
};

../../core/actions/index.js

import notify from './notify';
import confirm from './confirm';

export default {
  notify,
  confirm
};

../../core/actions/confirm.js

let dismissConfirmation = ({Store}) => {
  Store.dispatch({
    type: DISMISS_CONFIRMATION
  });
};

export default {
  displayConfirmation({Store}, {title, message, callback}) {
    Store.dispatch({
      type: DISPLAY_CONFIRMATION,
      title,
      message,
      callback
    });
  },

  dismissConfirmation,

  confirm(context) {
    let {Store} = context;

    Store.getState().confirm.callback();
    dismissConfirmation(context);
  }
};

非常感谢任何帮助!

-- 编辑 --

已尝试将 confirm.js 更改为:

../../core/actions/confirm.js

export const dismissConfirmation = ({Store}) => {
  Store.dispatch({
    type: DISMISS_CONFIRMATION
  });
};

export const displayConfirmation = ({Store}, {title, message, callback}) => {
  Store.dispatch({
    type: DISPLAY_CONFIRMATION,
    title,
    message,
    callback
  });
};

export const confirm = (context) => {
  let {Store} = context;

  Store.getState().confirm.callback();
  dismissConfirmation(context);
};

但仍然出现相同的未定义错误。

如果我尝试在 actions/ticket.js 处将 confirm.displayConfirmation 更改为 displayConfirmation,则会出现以下错误:

Uncaught TypeError: displayConfirmation is not a function

把你confirm.js换成这个

export const dismissConfirmation = ({Store}) => {
  Store.dispatch({
    type: DISMISS_CONFIRMATION
  });
};


export const displayConfirmation({Store}, {title, message, callback}) {
  Store.dispatch({
    type: DISPLAY_CONFIRMATION,
    title,
    message,
    callback
  });
},



export const confirm(context) {
  let {Store} = context;

  Store.getState().confirm.callback();
  dismissConfirmation(context);
}

现在您可以像这样在其他文件中导入这些函数

import { 
  displayConfirmation, 
  confirm, 
  dismissConfirmation 
} from '../../core/actions';

您混淆了命名导出和默认导出的概念,请阅读这篇文章Named exports vs default exports

根据@mzparacha 的建议,以下是最终更改。

../../core/actions/confirm.js

export const dismissConfirmation = ({Store}) => {
  Store.dispatch({
    type: DISMISS_CONFIRMATION
  });
};

export const displayConfirmation = ({Store}, {title, message, callback}) => {
  Store.dispatch({
    type: DISPLAY_CONFIRMATION,
    title,
    message,
    callback
  });
};

export const confirm = (context) => {
  let {Store} = context;

  Store.getState().confirm.callback();
  dismissConfirmation(context);
};

但是在导入部分,改为如下所示:

actions/ticket.js

import * as confirm from '../../core/actions/confirm';
...

其余的仍然存在。像魅力一样工作。谢谢@mzparacha