I came across some code looking like this where myProp was reportedly not being used, even though it was.
render() {
const { props } = this;
const { myProp } = props;
someFunction(myProp)
}
MyComponent.propTypes = {
myProp: PropTypes.number,
};
It seems the double desctructure confused the rule because a change to the code below fixed it.
render() {
const { myProp } = this.props;
someFunction(myProp)
}
I think it may be similar to https://github.com/yannickcr/eslint-plugin-react/issues/933, except this one is not such an anti-pattern. It looks very strange on my reduced version, but in a context with more variables can be more natural.
I think destructuring props off of this is pretty rare, but i agree it should work.
In my case the code was better after the fix, but I agree it should work.
Hello! Just showing my support for this bug to be fixed :-) :+1:
Running into this all over our codebase. Here's a reduction of one of the cases, first the output, then the code:
C:\w\rnps-home-ui\packages\home-ui\bug.js
5:13 error 'maxItems' PropType is defined but prop is never used react/no-unused-prop-types
6:27 error 'itemOpacityOutputRange' PropType is defined but prop is never used react/no-unused-prop-types
7:27 error 'textOpacityOutputRange' PropType is defined but prop is never used react/no-unused-prop-types
code:
// @flow
import * as React from 'react';
type Props = {
maxItems: number,
itemOpacityOutputRange: Array<number>,
textOpacityOutputRange: Array<number>,
itemScaleOutputRange: Array<number>,
children: Object => React.Node,
};
type State = {
foo: number,
bar: number,
};
function computeStateFromProps(props: Props) {
const { maxItems, itemOpacityOutputRange, textOpacityOutputRange, itemScaleOutputRange } = props;
if (maxItems && itemOpacityOutputRange && textOpacityOutputRange && itemScaleOutputRange) {
return { foo: 0, bar: 0 };
}
return { foo: 1, bar: 0 };
}
export default class X extends React.PureComponent<Props, State> {
constructor(props: Props) {
super(props);
this.state = computeStateFromProps(props);
}
animateItem = (index: ?number) => {
const { itemScaleOutputRange } = this.props;
if (itemScaleOutputRange && index) return 0;
return 1;
};
render() {
const {
animateItem,
props: { children },
} = this;
return <>{children({ animateItem })}</>;
}
}
@matthargett The rule only considered props.foo as used if it is used directly inside the component. Passing the props to a function and use props.foo will not work. You can work around it by doing:
this.state = computeStateFromProps({
maxItems: props.maxItems,
itemOpacityOutputRange: props.itemOpacityOutputRange,
...
})
Passing the props or state object around is a massive antipattern; always extract the props you need directly, and then pass them separately, or as a new object, to other functions.
Most helpful comment
Hello! Just showing my support for this bug to be fixed :-) :+1: