【问题标题】:TypeScript - invoking React prop with EnzymeTypeScript - 使用 Enzyme 调用 React 道具
【发布时间】:2018-09-02 01:25:54
【问题描述】:

我正在尝试将使用 Enzyme 的 Jest 测试转换为 TypeScript,但遇到了一种我不确定如何处理的特殊情况。基本上,我试图调用一个作为道具传递给子组件的函数。我看到的错误是:

spec/javascript/_common/components/sidebar_spec.tsx:85:5 - 错误 TS2349:

Cannot invoke an expression whose type lacks a call signature. Type '{}' has no compatible call signatures.

85     component.find(Link).at(0).prop('onNavigate')();
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

如何克服这个错误?不确定它是否有帮助,但更多的测试背景:

it('does not hide the sidebar after a link is clicked', () => {
  const component = shallow(<Sidebar />);

  component.find(Link).at(0).prop('onNavigate')();
  component.update();

  expect(component.find(Link)).toHaveLength(3);
});

还有来自Sidebar 组件的一段代码:

class Sidebar extends React.Component<any, any> {

  ...

  hideIfMobile() {
    const {mobile} = this.state;

    if (mobile) { this.setState({visible: false}); }
  }

  render() {
    const {visible} = this.state;

    if (!visible) {
      return (
        <div className='sidebar sidebar--hidden'>
          {this.sidebarToggle()}
        </div>
      );
    }

    const linkProps = {
      baseClass: 'sidebar__link',
      onNavigate: this.hideIfMobile,
    };

    return (
      <div className='sidebar sidebar--visible'>
        <h2 className='sidebar__header'>{'Menu'}{this.sidebarToggle()}</h2>
        <hr className='sidebar__divider' />
        <Link to='root' {...linkProps}><h2>{'FOCUS'}</h2></Link>
        <Link to='tasks' {...linkProps}><h2>{'ALL TASKS'}</h2></Link>
        <Link to='timeframes' {...linkProps}><h2>{'TIMEFRAMES'}</h2></Link>
      </div>
    );
  }
}

Link 组件被包裹在react-redux:

import {connect} from 'react-redux';

import Link from 'src/route/components/link';
import {getRouteName} from 'src/route/selectors';
import {setRoute} from 'src/route/action_creators';

function mapStateToProps(state) {
  return {routeName: getRouteName(state)};
}

export default connect(mapStateToProps, {setRoute})(Link);

和实际的组件:

class Link extends React.Component<any, any> {
  navigate(event) {
    event.preventDefault();

    const {onNavigate, params, setRoute, to} = this.props;

    setRoute({name: to, ...params});

    if (onNavigate) { onNavigate(); }
  }

  path() {
    const {params, to} = this.props;
    const pathParams = mapValues(params, value => value.toString());

    return findRoute(to).toPath(pathParams);
  }

  className() {
    const {baseClass, className, to, routeName} = this.props;

    return classnames(
      baseClass,
      {[`${baseClass}--active`]: baseClass && routeName === to},
      className,
    );
  }

  render() {
    const {children} = this.props;

    return (
      <a
        href={this.path()}
        className={this.className()}
        onClick={this.navigate}
      >
        {children}
      </a>
    );
  }
}

【问题讨论】:

  • 请将Link的定义添加到问题中。当我将其定义为 class Link extends React.Component&lt;{baseClass: string, onNavigate: () =&gt; void}, {}&gt; {} 时,我没有收到错误消息。
  • 已添加。在这种情况下,我也使用class 语法。但是,它也封装在 react-redux 容器中。
  • connect 调用生成的组件的 props 类型推断可能有问题。为了重现这个问题,我需要知道getRouteNamesetRoute 的类型。或者您可以自行调查,首先将鼠标悬停在 export default connect... 中的 default 上,查看类型是什么。
  • @MattMcCutchen 不确定getRouteNamesetRoute 在这种情况下是否相关。当我完全删除它们时,我仍然看到相同的错误。当我删除动作创建者和状态时,connect 调用的返回是(alias) connect(): InferableComponentEnhancerWithProps&lt;DispatchProp&lt;AnyAction&gt;, {}&gt; (+11 overloads)

标签: reactjs typescript jestjs enzyme


【解决方案1】:

原来Link 在这种情况下之前在我的测试文件中定义为:

const Link = 'Connect(Link)';

我将其切换为导入实际的链接容器,它解决了问题。

import Link from 'src/route/containers/link';

【讨论】:

    猜你喜欢
    • 2019-09-03
    • 2021-09-27
    • 2019-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-22
    相关资源
    最近更新 更多