This library has been absorbed into ember-resources
, here:
https://ember-resources.pages.dev/modules/util_map
This addon provides a useArrayMap
function which returns a resource that
reactively maps data per-element, so that when the overall collection is dirtied,
only the changed/new/removed elements affect the mapped collection.
This technique requires that your elements be mapped to be object-like so that iteration can rely on object identity to optimize loop iteration.
- Ember.js v3.25+
- TypeScript v4.2+
npm install ember-array-map-resource
# or
yarn add ember-array-map-resource
# or
ember install ember-array-map-resource
This is most useful for library authors that may not have control of how an array of items
is updated. It's common in modern JS to replace entire arrays when adding/removing/changing
items in arrays -- useArrayMap
provides a technique to re-optimize how updates within your
library are handled. Folks can replace an entire array, and as long as object-identity is
maintained.
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { useArrayMap } from 'ember-array-map-resource';
export default class MyComponent extends Component {
@tracked records = [];
mappedRecords = useArrayMap(this, {
data: () => this.records,
map: (record) => someTransform(record)
});
@action someTransform(record) {
return /* ... ✂️ ... */
}
}
NOTE: each
performance is handled by ember, and tweaks to its behavior can be tweaked.
SEE: https://guides.emberjs.com/release/components/looping-through-lists/
NOTE: useArrayMap
will have (very slightly) higher initial rendering time.
It's not meant to be faster than properly managed vanilla arrays.
useArrayMap
's purpose is for making it harder for users to de-optimize their iteration.
The above example could be achieved with inline-helpers and without a resource via:
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
export default class MyComponent extends Component {
@tracked records = [];
@action someTransform(record) {
return /* ... ✂️ ... */
}
}
So, why would you want to use a resource if you can acheive the same with a let
?
As a library author, you may be transforming data that you yourself don't have a say in
how it gets rendered. For example, if your component template were {{yield this.records}}
,
the user would be required to both transform and optimize their loop.
However, with useArrayMap
and {{yield this.mappedRecords}}
, the user can be naïve about
the implementation details of the list, and still get performance benefits.
This could be helpful with
- headless list implementations, where the user provides the entirety of the UI.
- javascript-only map-loop optimizations
ArrayMap<Element extends object, MapTo>
- the return type fromuseArrayMap
- iterable
- array-index access
See the Contributing guide for details.
This project is licensed under the MIT License.
This library wouldn't be possible without the work of:
So much appreciate for the work both you have put in to Resources <3