Skip to content
masterclassBuddyTech Buzz5 fresh blogs · 5:00 AM IST

Redux Toolkit · Module

adapter.upsertOne

upsertOne inserts one entity when its ID is absent, or shallowly merges its fields into the existing entity with that ID. It is generated by createEntityAdapter and can be used as an adapter operation or slice reducer.

How it works

Call the adapter reducer with the entity state and one entity, or use it directly as a slice reducer. The entity's ID determines whether Redux Toolkit adds a new record or shallowly merges matching fields into the existing record.

Syntax

upsertOne<S extends EntityState<T>>(state: S, entity: T): S
upsertOne<S extends EntityState<T>>(state: S, entity: PayloadAction<T>): S

Parameters

NameTypeDescription
stateEntityState<T>Normalized entity state containing the adapter-managed IDs and entities.
entityT | PayloadAction<T>The entity to insert or shallowly merge; the API also accepts a PayloadAction<T>.

Returns

The updated entity state, with the signature upsertOne<S extends EntityState<T>>(state: S, entity: T): S or upsertOne<S extends EntityState<T>>(state: S, entity: PayloadAction<T>): S.

Key points

  • upsertOne operates on exactly one entity rather than an array or keyed collection.
  • The entity's ID determines whether the operation follows the update path.
  • For an existing record, only top-level fields from the incoming entity are merged.
  • Incoming matching fields overwrite their existing top-level values.
  • A missing ID causes the adapter to insert the entity into the normalized state.

Common mistakes

  • Nested values are not merged recursively: an incoming nested object replaces the entire existing nested object.

Example: Upsert one normalized entity

const booksAdapter = createEntityAdapter<Book>();

const booksSlice = createSlice({
  name: "books",
  initialState: booksAdapter.getInitialState(),
  reducers: {
    bookReceived: booksAdapter.upsertOne,
  },
});

The reducer inserts a new book or shallowly merges it into the existing book with the same ID.

When to use it

Synchronize one server entity

A single API response may represent either a new record or a changed record.

Handle entity-received actions

A slice can register the adapter method as the handler for an action carrying one entity.

Maintain normalized collections

Normalized state can update one record without manually editing both IDs and entities.

Interview questions

QWhat does upsertOne do?

It accepts one entity and checks its ID against the normalized state. If the ID is present, matching fields are shallowly merged; otherwise, the entity is added.

Follow-up: What happens to a nested object during the merge? It replaces the existing nested object wholesale rather than being recursively merged.

QWhat inputs can upsertOne receive?

Its signatures accept either a plain entity or a PayloadAction containing an entity. This allows it to be used as an adapter call or assigned directly as a slice reducer.

Follow-up: Why can it be assigned directly to a slice reducer? Redux Toolkit reducer case handlers receive the state and action arguments expected by the adapter function.

QHow does upsertOne update an existing entity?

The entity ID controls whether the operation inserts or updates. Existing entities retain fields not mentioned by the incoming entity, while matching fields are overwritten.

Follow-up: When is this behavior risky? It can unintentionally discard sibling fields inside nested objects, so flat normalized entities are safer.

  • createEntityAdapter
  • EntityState
  • upsertMany
  • updateOne
  • updateMany
  • getInitialState

Source: createEntityAdapter. Checked 2026-10-15.