Synchronize one server entity
A single API response may represent either a new record or a changed record.
Redux Toolkit · Module
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.
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.
upsertOne<S extends EntityState<T>>(state: S, entity: T): S
upsertOne<S extends EntityState<T>>(state: S, entity: PayloadAction<T>): S| Name | Type | Description |
|---|---|---|
state | EntityState<T> | Normalized entity state containing the adapter-managed IDs and entities. |
entity | T | PayloadAction<T> | The entity to insert or shallowly merge; the API also accepts a PayloadAction<T>. |
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.
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.
A single API response may represent either a new record or a changed record.
A slice can register the adapter method as the handler for an action carrying one entity.
Normalized state can update one record without manually editing both IDs and entities.
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.
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.
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.
createEntityAdapterEntityStateupsertManyupdateOneupdateManygetInitialState