Skip to content

Commit 2010205

Browse files
authored
Merge pull request #1518 from petersendidit/1068-fix
Handle no-props-unused-props in custom validators
2 parents baa939c + 2b4776a commit 2010205

File tree

2 files changed

+94
-15
lines changed

2 files changed

+94
-15
lines changed

lib/rules/no-unused-prop-types.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,13 @@ module.exports = {
791791
types.name = key;
792792
types.node = value;
793793
declaredPropTypes.push(types);
794+
// Handle custom prop validators using props inside
795+
if (
796+
value.type === 'ArrowFunctionExpression'
797+
|| value.type === 'FunctionExpression'
798+
) {
799+
markPropTypesAsUsed(value);
800+
}
794801
});
795802
break;
796803
case 'MemberExpression':

tests/lib/rules/no-unused-prop-types.js

Lines changed: 87 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -829,10 +829,10 @@ ruleTester.run('no-unused-prop-types', rule, {
829829
type PropsA = { a: string }
830830
type PropsB = { b: string }
831831
type Props = PropsA & PropsB;
832-
832+
833833
class MyComponent extends React.Component {
834834
props: Props;
835-
835+
836836
render() {
837837
return <div>{this.props.a} - {this.props.b}</div>
838838
}
@@ -848,7 +848,7 @@ ruleTester.run('no-unused-prop-types', rule, {
848848
849849
class Bar extends React.Component {
850850
props: Props & PropsC;
851-
851+
852852
render() {
853853
return <div>{this.props.foo} - {this.props.bar} - {this.props.zap}</div>
854854
}
@@ -864,7 +864,7 @@ ruleTester.run('no-unused-prop-types', rule, {
864864
865865
class Bar extends React.Component {
866866
props: Props & PropsC;
867-
867+
868868
render() {
869869
return <div>{this.props.foo} - {this.props.bar} - {this.props.zap}</div>
870870
}
@@ -876,12 +876,12 @@ ruleTester.run('no-unused-prop-types', rule, {
876876
type PropsB = { foo: string };
877877
type PropsC = { bar: string };
878878
type Props = PropsB & {
879-
zap: string
879+
zap: string
880880
};
881881
882882
class Bar extends React.Component {
883883
props: Props & PropsC;
884-
884+
885885
render() {
886886
return <div>{this.props.foo} - {this.props.bar} - {this.props.zap}</div>
887887
}
@@ -893,12 +893,12 @@ ruleTester.run('no-unused-prop-types', rule, {
893893
type PropsB = { foo: string };
894894
type PropsC = { bar: string };
895895
type Props = {
896-
zap: string
896+
zap: string
897897
} & PropsB;
898898
899899
class Bar extends React.Component {
900900
props: Props & PropsC;
901-
901+
902902
render() {
903903
return <div>{this.props.foo} - {this.props.bar} - {this.props.zap}</div>
904904
}
@@ -2208,6 +2208,78 @@ ruleTester.run('no-unused-prop-types', rule, {
22082208
`,
22092209
settings: {react: {flowVersion: '0.53'}},
22102210
parser: 'babel-eslint'
2211+
}, {
2212+
// Issue #1068
2213+
code: `
2214+
class MyComponent extends Component {
2215+
static propTypes = {
2216+
validate: PropTypes.bool,
2217+
options: PropTypes.array,
2218+
value: ({options, value, validate}) => {
2219+
if (!validate) return;
2220+
if (options.indexOf(value) < 0)
2221+
throw new Errow('oops');
2222+
}
2223+
}
2224+
2225+
render() {
2226+
return <ul>
2227+
{this.props.options.map(option =>
2228+
<li className={this.props.value == option && "active"}>{option}</li>
2229+
)}
2230+
</ul>
2231+
}
2232+
}
2233+
`,
2234+
parser: 'babel-eslint'
2235+
}, {
2236+
// Issue #1068
2237+
code: `
2238+
class MyComponent extends Component {
2239+
static propTypes = {
2240+
validate: PropTypes.bool,
2241+
options: PropTypes.array,
2242+
value: function ({options, value, validate}) {
2243+
if (!validate) return;
2244+
if (options.indexOf(value) < 0)
2245+
throw new Errow('oops');
2246+
}
2247+
}
2248+
2249+
render() {
2250+
return <ul>
2251+
{this.props.options.map(option =>
2252+
<li className={this.props.value == option && "active"}>{option}</li>
2253+
)}
2254+
</ul>
2255+
}
2256+
}
2257+
`,
2258+
parser: 'babel-eslint'
2259+
}, {
2260+
// Issue #1068
2261+
code: `
2262+
class MyComponent extends Component {
2263+
static propTypes = {
2264+
validate: PropTypes.bool,
2265+
options: PropTypes.array,
2266+
value({options, value, validate}) {
2267+
if (!validate) return;
2268+
if (options.indexOf(value) < 0)
2269+
throw new Errow('oops');
2270+
}
2271+
}
2272+
2273+
render() {
2274+
return <ul>
2275+
{this.props.options.map(option =>
2276+
<li className={this.props.value == option && "active"}>{option}</li>
2277+
)}
2278+
</ul>
2279+
}
2280+
}
2281+
`,
2282+
parser: 'babel-eslint'
22112283
}
22122284
],
22132285

@@ -2796,10 +2868,10 @@ ruleTester.run('no-unused-prop-types', rule, {
27962868
type PropsA = { a: string }
27972869
type PropsB = { b: string }
27982870
type Props = PropsA & PropsB;
2799-
2871+
28002872
class MyComponent extends React.Component {
28012873
props: Props;
2802-
2874+
28032875
render() {
28042876
return <div>{this.props.a}</div>
28052877
}
@@ -2818,7 +2890,7 @@ ruleTester.run('no-unused-prop-types', rule, {
28182890
28192891
class Bar extends React.Component {
28202892
props: Props & PropsC;
2821-
2893+
28222894
render() {
28232895
return <div>{this.props.foo} - {this.props.bar}</div>
28242896
}
@@ -2833,12 +2905,12 @@ ruleTester.run('no-unused-prop-types', rule, {
28332905
type PropsB = { foo: string };
28342906
type PropsC = { bar: string };
28352907
type Props = PropsB & {
2836-
zap: string
2908+
zap: string
28372909
};
28382910
28392911
class Bar extends React.Component {
28402912
props: Props & PropsC;
2841-
2913+
28422914
render() {
28432915
return <div>{this.props.foo} - {this.props.bar}</div>
28442916
}
@@ -2853,12 +2925,12 @@ ruleTester.run('no-unused-prop-types', rule, {
28532925
type PropsB = { foo: string };
28542926
type PropsC = { bar: string };
28552927
type Props = {
2856-
zap: string
2928+
zap: string
28572929
} & PropsB;
28582930
28592931
class Bar extends React.Component {
28602932
props: Props & PropsC;
2861-
2933+
28622934
render() {
28632935
return <div>{this.props.foo} - {this.props.bar}</div>
28642936
}

0 commit comments

Comments
 (0)