UNPKG

2.59 kBJavaScriptView Raw
1const {pascalCase} = require('change-case');
2const Components = require('eslint-plugin-react/lib/util/Components');
3
4const {docsUrl} = require('../utilities');
5
6module.exports = {
7 meta: {
8 docs: {
9 description: 'Disallow public members within React component classes',
10 category: 'Best Practices',
11 recommended: true,
12 uri: docsUrl('react-prefer-private-members'),
13 },
14 },
15
16 create: Components.detect((context, components, utils) => {
17 let isES6Component = 0;
18 let componentName = null;
19
20 function report({node, componentName: classComponent}) {
21 const {
22 key: {name},
23 } = node;
24
25 context.report({
26 node,
27 message: `'{{name}}' should be a private member of '{{classComponent}}'.`,
28 data: {name, classComponent},
29 });
30 }
31
32 return {
33 ClassDeclaration(node) {
34 if (utils.isES6Component(node)) {
35 isES6Component++;
36 }
37 componentName = node.id.name;
38 },
39 'ClassDeclaration:exit': function(node) {
40 if (utils.isES6Component(node)) {
41 isES6Component--;
42 }
43 },
44 ClassProperty(node) {
45 if (isES6Component === 0 || isValid(node)) {
46 return;
47 }
48
49 report({node, componentName});
50 },
51 MethodDefinition(node) {
52 if (isES6Component === 0 || isValid(node)) {
53 return;
54 }
55
56 report({node, componentName});
57 },
58 };
59 }),
60};
61
62function isValid(node) {
63 return (
64 node.accessibility === 'private' ||
65 isReactLifeCycleMethod(node) ||
66 isReactStaticProperty(node) ||
67 isConstructor(node) ||
68 isCompoundComponentMember(node)
69 );
70}
71
72function isReactLifeCycleMethod({key: {name}}) {
73 return [
74 'getDerivedStateFromProps',
75 'componentWillMount',
76 'UNSAFE_componentWillMount',
77 'componentDidMount',
78 'componentWillReceiveProps',
79 'UNSAFE_componentWillReceiveProps',
80 'shouldComponentUpdate',
81 'componentWillUpdate',
82 'UNSAFE_componentWillUpdate',
83 'getSnapshotBeforeUpdate',
84 'componentDidUpdate',
85 'componentDidCatch',
86 'componentWillUnmount',
87 'getChildContext',
88 'context',
89 'state',
90 'render',
91 ].some((method) => method === name);
92}
93
94function isReactStaticProperty({key: {name}}) {
95 return [
96 'propTypes',
97 'contextTypes',
98 'childContextTypes',
99 'defaultProps',
100 'displayName',
101 ].some((method) => method === name);
102}
103
104function isConstructor({kind}) {
105 return kind === 'constructor';
106}
107
108function isCompoundComponentMember({key: {name}}) {
109 return name === pascalCase(name);
110}