Doorgaan naar hoofdinhoud

Array Methods Plug-in

[Onofficiële Beta-vertaling]

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:

MethodReturnsDescription
push()New lengthAdds elements to the end
pop()Removed elementRemoves and returns the last element
shift()Removed elementRemoves and returns the first element
unshift()New lengthAdds elements to the beginning
splice()Removed elementsAdds/removes elements at any position
sort()The draft arraySorts elements in place
reverse()The draft arrayReverses 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.

MethodReturnsDrafts?
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.

MethodReturnsDrafts?
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:

MethodReturns
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:

MethodDescription
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

CategoryMethodsReturnsMutations Track?
Subsetfilter, slice, find, findLastDraft proxies✅ Yes
Transformconcat, flatBase values❌ No
PrimitiveindexOf, includes, some, every, findIndex, findLastIndex, lastIndexOf, join, toString, toLocaleStringPrimitivesN/A
Mutatingpush, pop, shift, unshift, splice, sort, reverseVarious✅ Yes (modifies draft)
Not Overriddenmap, flatMap, forEach, reduce, reduceRightStandard 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, every op grote arrays gebruikt

  • Prestatieprofiling 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
})
})