1 | module.exports = function pureComponentFallback({ types: t, template }) {
|
2 | const buildPureOrNormalSuperclass = () => t.LogicalExpression('||',
|
3 | t.memberExpression(t.identifier('React'), t.identifier('PureComponent')),
|
4 | t.memberExpression(t.identifier('React'), t.identifier('Component')));
|
5 |
|
6 | const buildShouldComponentUpdate = () => {
|
7 | const method = t.classMethod(
|
8 | 'method',
|
9 | t.logicalExpression(
|
10 | '&&',
|
11 | t.unaryExpression('!', t.memberExpression(t.identifier('React'), t.identifier('PureComponent'))),
|
12 | t.stringLiteral('shouldComponentUpdate')
|
13 | ),
|
14 | [t.identifier('nextProps'), t.identifier('nextState')],
|
15 | t.blockStatement([template('return !shallowEqual(this.props, nextProps) || !shallowEqual(this.state, nextState);')()]),
|
16 | true
|
17 | );
|
18 | return method;
|
19 | };
|
20 |
|
21 | function superclassIsPureComponent(path) {
|
22 | const superclass = path.get('superClass');
|
23 |
|
24 | if (t.isIdentifier(superclass)) {
|
25 | return superclass.node.name === 'PureComponent';
|
26 | }
|
27 |
|
28 | if (t.isMemberExpression(superclass)) {
|
29 |
|
30 | return superclass.get('object').node.name === 'React'
|
31 | && superclass.get('property').node.name === 'PureComponent';
|
32 | }
|
33 |
|
34 | return false;
|
35 | }
|
36 |
|
37 | return {
|
38 | visitor: {
|
39 | Program: {
|
40 | exit({ node }, { file }) {
|
41 | if (file.get('addShallowEqualImport')) {
|
42 | const shallowEqualImportDeclaration = t.importDeclaration([
|
43 | t.importDefaultSpecifier(t.identifier('shallowEqual')),
|
44 | ], t.stringLiteral('enzyme-shallow-equal'));
|
45 | node.body.unshift(shallowEqualImportDeclaration);
|
46 | }
|
47 | },
|
48 | },
|
49 |
|
50 | ClassDeclaration(path, { file }) {
|
51 | if (superclassIsPureComponent(path)) {
|
52 | const superclassPath = path.get('superClass');
|
53 |
|
54 |
|
55 | superclassPath.replaceWith(buildPureOrNormalSuperclass());
|
56 |
|
57 |
|
58 | const existingSCU = path.get('body').get('body').find((
|
59 | p => p.isClassMethod() && p.get('key').node.name === 'shouldComponentUpdate'
|
60 | ));
|
61 |
|
62 | if (!existingSCU) {
|
63 | file.set('addShallowEqualImport', true);
|
64 | path.get('body').unshiftContainer('body', buildShouldComponentUpdate());
|
65 | }
|
66 | }
|
67 | },
|
68 | },
|
69 | };
|
70 | };
|