-
-
Notifications
You must be signed in to change notification settings - Fork 68
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 deprecation guide for array prototype extensions for V5 #1192
base: main
Are you sure you want to change the base?
Add deprecation guide for array prototype extensions for V5 #1192
Conversation
✅ Deploy Preview for ember-deprecations ready!
To edit notification comments on pull requests, go to your Netlify site settings. |
After: | ||
```js | ||
const someArray = [{ food: 'apple', isFruit: true }, { food: 'beans', isFruit: false }]; | ||
someArray.any(el => el.isFruit); // true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Array doesn't have .any()
method. I think .some()
is appropriate here.
someArray.any(el => el.isFruit); // true | |
someArray.some(el => el.isFruit); // true |
? a.food?.localCompare(b.food) | ||
: a.isFruit - b.isFruit; | ||
}); // [{ food: 'apple', isFruit: true }, { food: 'beans', isFruit: false }] | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, I think that it would have to be stated here that this implementation is not as robust as Ember Array's .sortBy
. It has field names hardcoded and can't take an arbitrary number of field names.
Before: | ||
```js | ||
const someArray = [{ food: 'apple', isFruit: true }, { food: 'beans', isFruit: false }]; | ||
someArray.toArray(); // [{ food: 'apple', isFruit: true }, { food: 'beans', isFruit: false }] | ||
``` | ||
|
||
After: | ||
```js | ||
const someArray = [{ food: 'apple', isFruit: true }, { food: 'beans', isFruit: false }]; | ||
[...someArray] // [{ food: 'apple', isFruit: true }, { food: 'beans', isFruit: false }] | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I never used this method but the docs are saying:
Simply converts the object into a genuine array. The order is not guaranteed. Corresponds to the method implemented by Prototype.
So I guess an example should show how to convert an object into an array. I'd have to check how the original function works but would this be expected?
const person = {
firstName: 'John',
lastName: 'Doe'
};
Object.entries(person); // [ [ 'firstName', 'John' ], [ 'lastName', 'Doe' ] ]
🤔
Co-authored-by: Tomek Nieżurawski <[email protected]>
Co-authored-by: Tomek Nieżurawski <[email protected]>
Co-authored-by: Tomek Nieżurawski <[email protected]>
Co-authored-by: Tomek Nieżurawski <[email protected]>
thank you so much for reviewing @tniezurawski ! |
|
||
@action | ||
pushObject(value) { | ||
this.abc = [...this.abc, value]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little confused by the difference between this example and the pushObject
example above which uses TrackedArray
. Is it a requirement to assign to this.abc
when using @tracked
but not when using TrackedArray
? Or is the different method shown to indicate that both approaches are valid?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, @tracked
will only trigger the reactivity when a new value gets assigned. When the existing native array is internally mutated, like calling .push()
, then this will not be reactive. In opposite to TrackedArray
, which does this kind of deep tracking. So I think the example is right.
|
||
@action | ||
pushObjects(values) { | ||
this.abc.splice(this.abc.length, 0, ...values); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this.abc.push(...values)
work here? It would be simpler and match the first after
example for pushObject
above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, i think so!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lots of details in that migration guide, great work @smilland! I know this has been quite a whole since you worked on this, so would you still be available to look into and work on the provided suggestions?
The RFC was accepted long ago, so I think we can and should get this merged asap, as I would like to also get the actual deprecation implemented before we miss the time window for the v6 release!
} | ||
} | ||
|
||
[new Person('Tom'), new Person('Joe')].map(person => person['greet']?.('Hi')); // ['Hi Tom', 'Hi Joe'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[new Person('Tom'), new Person('Joe')].map(person => person['greet']?.('Hi')); // ['Hi Tom', 'Hi Joe'] | |
[new Person('Tom'), new Person('Joe')].forEach(person => person.greet('Hi')); // ['Hi Tom', 'Hi Joe'] |
I think forEach
is more appropriate than map
here, since we don't use the value returned by map
. Also the method call can be simplified as suggested I believe? invoke
might do that optional chaining internally, but if people were to rewrite that code to native, I think this is what they would/should write.
: a.isFruit - b.isFruit; | ||
}); // [{ food: 'apple', isFruit: true }, { food: 'beans', isFruit: false }] | ||
``` | ||
#### `toArray` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this example even needed? I think you would use toArray
an an array-like object like A()
, to turn it into a native array. But here we are only dealing with native arrays, so what's the point of toArray()
usage then?
const someArray = ['a', 'a', 'b', 'b'] | ||
[...new Set(someArray)] // ['a', 'b'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This example should match the one above, so rather like:
const someArray = ['a', 'a', 'b', 'b'] | |
[...new Set(someArray)] // ['a', 'b'] | |
const someArray = [1, 2, 3, undefined, 3]; | |
[...new Set(someArray)] // [1, 2, 3, undefined] |
id: deprecate-array-prototype-extensions | ||
title: "Deprecate array prototype extensions" | ||
until: '6.0.0' | ||
since: '5.0.0' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we update this to the current one on main
, assuming we get the deprecation implemented in that version?
since: '5.0.0' | |
since: '5.10.0' |
import { TrackedArray } from 'tracked-built-ins'; | ||
|
||
export default class SampleComponent extends Component { | ||
abc = new TrackedArray(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
abc = new TrackedArray(); | |
abc = new TrackedArray(['x', 'y', 'z', 'x']); |
|
||
@action | ||
pushObject(value) { | ||
this.abc = [...this.abc, value]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, @tracked
will only trigger the reactivity when a new value gets assigned. When the existing native array is internally mutated, like calling .push()
, then this will not be reactive. In opposite to TrackedArray
, which does this kind of deep tracking. So I think the example is right.
|
||
@action | ||
pushObjects(values) { | ||
this.abc.splice(this.abc.length, 0, ...values); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, i think so!
this.abc.splice(start, len); | ||
this.abc = [...this.abc]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this would also work, and be a bit simpler?
this.abc.splice(start, len); | |
this.abc = [...this.abc]; | |
this.abc.splice(start, len); | |
this.abc = this.abc; |
let loc = this.abc.length || 0; | ||
while (--loc >= 0) { | ||
let curValue = this.abc.at(loc); | ||
|
||
if (curValue === value) { | ||
this.abc.splice(loc, 1); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't a simple filer call work here?
let loc = this.abc.length || 0; | |
while (--loc >= 0) { | |
let curValue = this.abc.at(loc); | |
if (curValue === value) { | |
this.abc.splice(loc, 1); | |
} | |
} | |
this.abc.filter(item => item !== value); |
same for the related examples below...
RFC: Deprecate array prototype extensions
Rendered content
It's ready for review, though only can be merge after the RFC is approved.