Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add no-array-index-key rule #978

Merged
merged 6 commits into from
Dec 1, 2016
Merged

Add no-array-index-key rule #978

merged 6 commits into from
Dec 1, 2016

Conversation

lencioni
Copy link
Collaborator

This rule will warn when using the array index as the key. As a first
pass, I decided to implement this for Array.prototype.map, since that
is likely the most common case, but it theoretically could be expanded
to find other cases so I kept the naming more generic.

Like many rules, this one is imperfect and is prone to some false
positives and negatives. For instance, if someone defines a .map()
function on an object that doesn't have the same signature as
Array.prototype.map, this will likely end up warning in those cases.
However, I think the value of this rule outweighs its hypothetical
drawbacks.

@@ -0,0 +1,23 @@
# Prevent usage of Array index in keys

Warn if an element uses an Array index in its `key`.
Copy link
Collaborator

@EvHaus EvHaus Nov 25, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think adding a short description of why you might want to enable this rule would be good. Something like:

It's a bad idea to use the array index since it doesn't uniquely identify your elements. In cases where the array is sorted, the index will be changed, even though the element representing that index may be the same -- resulting in unnecessary render cycles.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I'll expand this document a little. I intended my next sentence to provide the reasoning, but perhaps it needs to be more explicit.

if (callee.property.type !== 'Identifier') {
return null;
}
if (callee.property.name !== 'map') {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add forEach and filter in here as well. It's easy enough to support it for those rare cases where users would iterate over elements in different ways.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see forEach for sure, but filter would be quite unusual. It should be easy enough to include though and I don't see any harm in it, so I'll add these.

@EvHaus
Copy link
Collaborator

EvHaus commented Nov 25, 2016

Nice. Would be really great if this could also support React.cloneElement, ala:

[].map((item, i) => {
    return React.cloneElement(someChild, {
        key: i
    })
})

@lencioni
Copy link
Collaborator Author

All feedback has been addressed! PTAL

Copy link
Member

@ljharb ljharb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, what about the .forEach method of a Map or Set?

otherThings.push(<Hello key={index} />);
});

things.some((thing, index) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about reduce, reduceRight, find?

@lencioni
Copy link
Collaborator Author

Also, what about the .forEach method of a Map or Set?

@ljharb What do you mean by this question? Are you referring to the name of the rule and documentation mentioning arrays?

@ljharb
Copy link
Member

ljharb commented Nov 28, 2016

@lencioni i mean, aMapOrSet.forEach(x => { somethingElse.push(<div key={x} />); }) or similar. Will these be caught as well, since there's no way to know if aMapOrSet is an array or not?

@lencioni
Copy link
Collaborator Author

@ljharb Yes, these will be caught as well for precisely the reason you mention. Likewise, so will any instance of any class that has one of these methods on it. This is what I was referring to about potential false positives in my commit message.

lencioni and others added 6 commits November 29, 2016 14:26
This rule will warn when using the array index as the `key`. As a first
pass, I decided to implement this for `Array.prototype.map`, since that
is likely the most common case, but it theoretically could be expanded
to find other cases so I kept the naming more generic.

Like many rules, this one is imperfect and is prone to some false
positives and negatives. For instance, if someone defines a `.map()`
function on an object that doesn't have the same signature as
`Array.prototype.map`, this will likely end up warning in those cases.
However, I think the value of this rule outweighs its hypothetical
drawbacks.
This makes the intention of this rule clearer.
Although some of these cover pretty unusual use-cases, they are easy
enough to support and are unlikely to have false positives.
This helps to cover more possible use-cases that we want to prevent with
this rule.
As @ljharb pointed out, this rule should spot array indexes when using
reduce. Since the index is the third argument to the reduce callback, I
needed to generalize some of my logic a bit to make this configurable
for each type of function.
I missed examples of this in my first pass at this documentation.
@lencioni
Copy link
Collaborator Author

@ljharb I believe I have addressed your feedback.

@lencioni lencioni merged commit fe32c7d into master Dec 1, 2016
@lencioni lencioni deleted the no-array-index-key branch December 1, 2016 17:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging this pull request may close these issues.

4 participants