首页 > 解决方案 > 为什么酶在装饰的子组件上给出“失败的道具类型”

问题描述

如果我使用高阶组件(HOC)作为装饰器,即

@withStyles({})
class Bar extends React.Component { ... }

我会用酶得到这个错误:

  console.error node_modules/prop-types/checkPropTypes.js:19
    Warning: Failed prop type: The prop `classes` is marked as required in `_class`, but its value is `undefined`.
        in _class

如果我使用函数形式,即

const Bar = withStyles({})(class extends React.Component { ... });

没有错误。

为什么?

请注意,此警告仅发生在子组件上;请参阅复制步骤中的代码以了解我的意思。

复制步骤

package.json

{
  "name": "test",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "test": "jest"
  },
  "author": "",
  "dependencies": {
    "prop-types": "^15.6.2",
    "react": "^16.4.1",
    "react-dom": "^16.4.1"
  },
  "devDependencies": {
    "babel-jest": "^23.2.0",
    "babel-plugin-transform-class-properties": "^6.24.1",
    "babel-plugin-transform-decorators-legacy": "^1.3.5",
    "babel-preset-env": "^1.7.0",
    "babel-preset-react": "^6.24.1",
    "enzyme": "^3.3.0",
    "enzyme-adapter-react-16": "^1.1.1",
    "jest": "^23.3.0"
  },
  "babel": {
    "plugins": [
      "transform-class-properties",
      "transform-decorators-legacy"
    ],
    "presets": [
      "env",
      "react"
    ]
  }
}

__tests__/app.test.js

import Adapter from 'enzyme-adapter-react-16';
import Enzyme from 'enzyme';
import PropTypes from 'prop-types';
import React from 'react';
import { shallow } from 'enzyme';

Enzyme.configure({ adapter: new Adapter() });

const withStyles = styles => Component => class extends React.Component {
  render() {
    return <Component classes={styles} />
  }
}

// This will produce a failed prop type warning:
@withStyles({})
class Bar extends React.Component {
  static propTypes = {
    classes: PropTypes.object.isRequired,
  }

  render() {
    return <div>test</div>;
  }
}

// This will NOT produce a failed prop type warning:
// const Bar = withStyles({})(class extends React.Component {
  // static propTypes = {
    // classes: PropTypes.object.isRequired,
  // }

  // render() {
    // return <div>test</div>;
  // }
// });

class Test extends React.Component {
  render() {
    return <Bar />;
  }
}

it('renders without crashing', () => {
  shallow(<Test />);
  expect(true).toBe(true);
});

npm t

有两个代码块:一个带有装饰,另一个(当前已注释掉)带有函数形式。只需注释掉装饰器块并取消注释功能表单块即可测试这两种情况。

这个问题最初是在使用 material-ui 时出现的,我可以确认这两种情况在视觉上呈现相同的 UI。这使我无法使用withStyles.

请注意,我在这里进行了更多调查:https ://github.com/airbnb/enzyme/issues/1505

标签: reactjsjestjsdecoratorenzyme

解决方案


@babel/plugin-proposal-decorators需求先于,@babel/plugin-proposal-class-properties即在package.json

  "babel": {
    "plugins": [
      "transform-decorators-legacy",
      "transform-class-properties"
    ],

推荐阅读