Array Methods Plug-in
Deze pagina is vertaald door PageTurner AI (beta). Niet officieel goedgekeurd door het project. Een fout gevonden? Probleem melden →
Overzicht
De Array Methods Plug-in (enableArrayMethods()) optimaliseert array-operaties binnen Immer producers door onnodige Proxy-creatie tijdens iteratie te vermijden. Dit levert aanzienlijke prestatieverbeteringen op voor array-intensieve operaties.
Waarom is dit belangrijk? Zonder de plug-in creëert elke toegang tot array-elementen tijdens iteratie (bijv. in filter, find, slice) een Proxy-object. Voor een array met 1000 elementen betekent dit 1000+ proxy-trap-aanroepen alleen al voor iteratie. Met de ingeschakelde plug-in ontvangen callbacks basiswaarden (niet-geproxied), en worden proxies alleen aangemaakt wanneer nodig voor mutatietracking.
Installatie
Activeer de plug-in eenmalig op het startpunt van je applicatie:
import {enableArrayMethods} from "immer"
enableArrayMethods()
Dit voegt ongeveer 2KB toe aan je bundelgrootte.
Mutatiefuncties
Deze methoden wijzigen de array ter plaatse en werken direct op de interne kopie van de draft zonder per-element proxies aan te maken:
| Method | Returns | Description |
|---|---|---|
push() | New length | Adds elements to the end |
pop() | Removed element | Removes and returns the last element |
shift() | Removed element | Removes and returns the first element |
unshift() | New length | Adds elements to the beginning |
splice() | Removed elements | Adds/removes elements at any position |
sort() | The draft array | Sorts elements in place |
reverse() | The draft array | Reverses the array in place |
import {produce, enableArrayMethods} from "immer"
enableArrayMethods()
const base = {items: [3, 1, 4, 1, 5]}
const result = produce(base, draft => {
draft.items.push(9) // Adds 9 to end
draft.items.sort() // Sorts: [1, 1, 3, 4, 5, 9]
draft.items.reverse() // Reverses: [9, 5, 4, 3, 1, 1]
})
Niet-muterende functies
Niet-muterende methoden worden gecategoriseerd op basis van hun returnwaarde:
Subsetoperaties (Returnen Drafts)
Deze methoden selecteren items die in de originele array bestaan en creëren draft-proxies voor de geretourneerde items. De callbacks ontvangen basiswaarden (de optimalisatie), maar de geretourneerde array bevat nieuw aangemaakte draft-proxies die terugwijzen naar de originele posities. Mutaties aan geretourneerde items ZULLEN de draftstatus beïnvloeden.
| Method | Returns | Drafts? |
|---|---|---|
filter() | Array of matching items | ✅ Yes |
slice() | Array of items in range | ✅ Yes |
find() | First matching item or undefined | ✅ Yes |
findLast() | Last matching item or undefined | ✅ Yes |
const base = {
items: [
{id: 1, value: 10},
{id: 2, value: 20},
{id: 3, value: 30}
]
}
const result = produce(base, draft => {
// filter returns drafts - mutations track back to original
const filtered = draft.items.filter(item => item.value > 15)
filtered[0].value = 999 // This WILL affect draft.items[1]
// find returns a draft - mutations track back
const found = draft.items.find(item => item.id === 3)
if (found) {
found.value = 888 // This WILL affect draft.items[2]
}
// slice returns drafts
const sliced = draft.items.slice(0, 2)
sliced[0].value = 777 // This WILL affect draft.items[0]
})
console.log(result.items[0].value) // 777
console.log(result.items[1].value) // 999
console.log(result.items[2].value) // 888
Transformatieoperaties (Returnen Basiswaarden)
Deze methoden creëren nieuwe arrays die externe items of herstructureerde data kunnen bevatten. Ze returnen basiswaarden, GEEN drafts. Mutaties aan geretourneerde items worden NIET teruggekoppeld naar de draftstatus.
| Method | Returns | Drafts? |
|---|---|---|
concat() | New combined array | ❌ No |
flat() | New flattened array | ❌ No |
const base = {items: [{id: 1, value: 10}]}
const result = produce(base, draft => {
// concat returns base values - mutations DON'T track
const concatenated = draft.items.concat([{id: 2, value: 20}])
concatenated[0].value = 999 // This will NOT affect draft.items[0]
// To actually use concat results, assign them:
draft.items = draft.items.concat([{id: 2, value: 20}])
})
// Original unchanged because concat result wasn't assigned
console.log(result.items[0].value) // 10 (unchanged)
Waarom dit onderscheid?
Subsetoperaties (
filter,slice,find) selecteren items uit de originele array. Het returnen van drafts zorgt dat mutaties doorwerken naar de bron.Transformatieoperaties (
concat,flat) creëren nieuwe datastructuren die externe items of herstructureerde data kunnen bevatten, waardoor drafttracking onpraktisch is.
Primitief-returnende functies
Deze methoden returnen primitieve waarden (getallen, booleans, strings). Geen trackingproblemen omdat primitieven niet draftable zijn:
| Method | Returns |
|---|---|
indexOf() | Number (index or -1) |
lastIndexOf() | Number (index or -1) |
includes() | Boolean |
some() | Boolean |
every() | Boolean |
findIndex() | Number (index or -1) |
findLastIndex() | Number (index or -1) |
join() | String |
toString() | String |
toLocaleString() | String |
const base = {
items: [
{id: 1, active: true},
{id: 2, active: false}
]
}
const result = produce(base, draft => {
const index = draft.items.findIndex(item => item.id === 2)
const hasActive = draft.items.some(item => item.active)
const allActive = draft.items.every(item => item.active)
console.log(index) // 1
console.log(hasActive) // true
console.log(allActive) // false
})
Niet-overschreven functies
De volgende methoden worden niet onderschept door de plug-in en werken via standaard Proxy-gedrag. Callbacks ontvangen drafts en mutaties tracken normaal:
| Method | Description |
|---|---|
map() | Transform each element |
flatMap() | Map then flatten |
forEach() | Execute callback for each element |
reduce() | Reduce to single value |
reduceRight() | Reduce from right to left |
const base = {
items: [
{id: 1, value: 10, nested: {count: 0}},
{id: 2, value: 20, nested: {count: 0}}
]
}
const result = produce(base, draft => {
// forEach receives drafts - mutations work normally
draft.items.forEach(item => {
item.value *= 2
})
// map is NOT overridden - callbacks receive drafts
// The returned array items are also drafts (extracted from draft.items)
const mapped = draft.items.map(item => item.nested)
// Mutations to the result array propagate back
mapped[0].count = 999 // ✅ This affects draft.items[0].nested.count
})
console.log(result.items[0].nested.count) // 999
Callback-gedrag
Voor overschreven methoden ontvangen callbacks basiswaarden (geen drafts). Dit is de kernoptimalisatie - het vermijdt het aanmaken van proxies voor elk element tijdens iteratie.
const base = {
items: [
{id: 1, value: 10},
{id: 2, value: 20}
]
}
produce(base, draft => {
draft.items.filter(item => {
// `item` is a base value here, NOT a draft
// Reading properties works fine
return item.value > 15
// But direct mutation here won't be tracked:
// item.value = 999 // ❌ Won't affect draft
})
// Instead, use the returned draft:
const filtered = draft.items.filter(item => item.value > 15)
filtered[0].value = 999 // ✅ This works because filtered[0] is a draft
})
Samenvatting return-gedrag methoden
| Category | Methods | Returns | Mutations Track? |
|---|---|---|---|
| Subset | filter, slice, find, findLast | Draft proxies | ✅ Yes |
| Transform | concat, flat | Base values | ❌ No |
| Primitive | indexOf, includes, some, every, findIndex, findLastIndex, lastIndexOf, join, toString, toLocaleString | Primitives | N/A |
| Mutating | push, pop, shift, unshift, splice, sort, reverse | Various | ✅ Yes (modifies draft) |
| Not Overridden | map, flatMap, forEach, reduce, reduceRight | Standard behavior | ✅ Yes (callbacks get drafts) |
Wanneer te gebruiken
Schakel de Array Methods Plug-in in wanneer:
Je applicatie significante array-iteratie binnen producers heeft
Je regelmatig methoden zoals
filter,find,some,everyop grote arrays gebruiktPrestatieprofiling array-operaties als knelpunt identificeert
De plug-in levert de meeste voordelen op voor:
Grote arrays (100+ elementen)
Frequente producer-aanroepen met array-operaties
Leesintensieve operaties (filteren, zoeken) waarbij de meeste elementen ongewijzigd blijven
Prestatievoordeel
Zonder de plug-in:
Elke array-elementtoegang tijdens iteratie creëert een Proxy
Een
filter()op 1000 elementen = 1000+ proxy-creaties
Met de plug-in:
Callbacks ontvangen basiswaarden direct
Proxies worden alleen aangemaakt voor de specifieke elementen die je daadwerkelijk wijzigt, of die voldoen aan de filtervoorwaarden
// Without plugin: ~3000+ proxy trap invocations
// With plugin: ~10-20 proxy trap invocations
const result = produce(largeState, draft => {
const filtered = draft.items.filter(x => x.value > threshold)
// Only items you mutate get proxied
filtered.forEach(item => {
item.processed = true
})
})