Jack Damon
Jack Damon

Reputation: 341

How to create entity IDs in the createSlice reducer prepare function

I'm having some trouble with the prepare callback function included in my addEntity reducer I include in redux-toolkit's createSlice function.

I'm trying to use the prepare callback to add unique IDs to my action payloads.

The redux-toolkit createSlice documentation says:

If you need to customize the creation of the payload value of an action creator by means of a prepare callback, the value of the appropriate field of the reducers argument object should be an object instead of a function. This object must contain two properties: reducer and prepare. The value of the reducer field should be the case reducer function while the value of the prepare field should be the prepare callback function.

Here is the code I am using (written w/ TypeScript):

import { createSlice, createEntityAdapter } from '@reduxjs/toolkit';
import { MyEntityType } from '../../js/types/MyEntityType';
import { v4 as uuidv4 } from 'uuid';

const myEntityAdapter = createEntityAdapter<MyEntityType>();

const { reducer, actions } = createSlice({
    name: 'myEntity',
    initialState: myEntityAdapter.getInitialState(),
    reducers: {
        addEntity: {
            reducer: myEntityAdapter.addOne,
            prepare: (payload) => ({...payload, id: uuidv4()}),
        },
        removeEntity: myEntityAdapter.removeOne,
        updateEntity: myEntityAdapter.updateOne,
    }
});

When I compile my app and test creating an entity using the addEntity action, however, the prepare callback doesn't appear to do anything.

Here is the action I dispatch using Redux DevTools:

{
 type: 'myEntity/addEntity',
 payload: {myPayloadTrait: 100, id: 'test'} // Expected behavior: this id should be overwritten in the prepare callback
}

Resulting state:

myEntity: {
    ids: {
        0:"test"
    },
    entities: {
        "test": {
            myPayloadTrait: 100
            id: "test"
        }
    }
}

Why doesn't my prepare callback overwrite the "test" id before the payload is passed to the reducer? Any help or guidance would be much appreciated.

Upvotes: 1

Views: 1619

Answers (1)

markerikson
markerikson

Reputation: 67567

The prepare callback must return an object that looks like {payload?, meta?, error?}. Your code is currently returning the intended payload directly.

Change it to:

addEntity: {
  reducer: myEntityAdapter.addOne,
  prepare: (payload) => ({
    payload: {
      ...payload,
      id: uuidv4()
    }
  }),
}

Upvotes: 2

Related Questions