Apply a batch synchronization
A normalized API response contains several new records and revisions to existing records.
Redux Toolkit · Module
adapter.upsertMany inserts multiple entities into normalized state and shallowly merges entities whose IDs already exist. It accepts an array or an ID-keyed record.
upsertMany accepts multiple entities and applies them to a normalized entity state. New IDs are inserted; existing entities receive a shallow merge, so omitted top-level properties remain while nested objects are replaced as whole values.
upsertMany<S extends EntityState<T>>(state: S, entities: T[]): S| Name | Type | Description |
|---|---|---|
state | S extends EntityState<T> | The normalized entity state being updated. |
entities | T[] | Record<EntityId, T> | Entities to insert or shallowly merge; this may be an array of T values or a Record<EntityId, T>. |
The updated normalized entity state; the generated case-reducer form returns the adapter-managed state.
import { createEntityAdapter, createSlice } from '@reduxjs/toolkit'
type Todo = { id: string; title: string; done: boolean }
const todos = createEntityAdapter<Todo>()
const todosSlice = createSlice({
name: 'todos',
initialState: todos.getInitialState(),
reducers: {
todosUpserted: todos.upsertMany,
},
})
const state = todosSlice.reducer(undefined, todosSlice.actions.todosUpserted([
{ id: '1', title: 'Read docs', done: false },
{ id: '2', title: 'Ship feature', done: true },
]))
console.log(state.entities['1'])Creates a normalized entity slice and uses the adapter reducer to insert or shallowly merge multiple todos.
A normalized API response contains several new records and revisions to existing records.
A slice receives entities from a fulfilled request or websocket batch.
Incoming records have flat top-level fields that can be safely merged.
adapter.upsertMany do?upsertMany handles a collection of entities in normalized state. It inserts entities whose IDs are absent and shallowly merges incoming fields into entities that already exist.
Follow-up: What happens to an existing nested object? The incoming nested value replaces the complete old nested object rather than being recursively merged.
upsertMany commonly used in a slice?Its reducer form receives the entity collection through the action payload. The adapter can be used as a case reducer in createSlice, where Redux Toolkit supplies the draft state.
Follow-up: Can the payload be keyed by ID? Yes; the documented API also accepts an object shaped like Record<EntityId, T>.
upsertMany differ from replacement updates?Unlike setMany, it preserves existing top-level properties that the incoming entity does not provide. Existing matching fields are overwritten, and new fields are added through the shallow merge.
Follow-up: When is setMany preferable? Use it when each supplied entity should replace its old version completely, including removal of omitted properties.
createEntityAdapterEntityStateaddManysetManyupsertOneupdateManygetInitialState