reduxjs / redux-toolkit

The official, opinionated, batteries-included toolset for efficient Redux development
https://redux-toolkit.js.org
MIT License
10.72k stars 1.17k forks source link

listenerMiddleware/error Error: [Immer] 'current' expects a draft, got: #4411

Closed zy-jtp closed 4 months ago

zy-jtp commented 5 months ago

Unhandled Runtime Error | Error: [Immer] 'current' expects a draft, got:

Example Repo

https://github.com/zy-jtp/rtk-next14-error

Context

The call triggering the error is a dispatch call to modals slice from an onClick callback

listenerApi.dispatch(
          modalsSlice.actions.openModal({
            dialogId: 'modify',
            closeable: !action.payload?.uncloseableModal,
          })
        )

its initial state comes from an entityAdapter

export const Modal = createEntityAdapter<ModalConfig, DialogId>({
  selectId: (modal) => modal.dialogId,
});
export const modalsSlice = createSlice({
initialState: Modal.getInitialState()
})

Runtime Error

listenerMiddleware/error Error: [Immer] 'current' expects a draft, got: 
    at die (immer.mjs:64:11)
    at current (immer.mjs:704:5)
    at splitAddedUpdatedEntities (redux-toolkit.modern.mjs:1454:74)
    at upsertManyMutably (redux-toolkit.modern.mjs:1577:30)
    at upsertOneMutably (redux-toolkit.modern.mjs:1574:12)
    at runMutator (redux-toolkit.modern.mjs:1423:9)
    at Object.operation [as upsertOne] (redux-toolkit.modern.mjs:1427:7)
    at openModal (modals.slice.ts:18:13)
    at eval (redux-toolkit.modern.mjs:780:20)
    at Immer2.produce (immer.mjs:593:20)
    at eval (redux-toolkit.modern.mjs:779:64)
    at Array.reduce (<anonymous>)
    at reducer (redux-toolkit.modern.mjs:760:25)
    at reducer (redux-toolkit.modern.mjs:1173:14)
    at combination (redux.mjs:327:31)
    at hu (<anonymous>:3:1043)
    at yu (<anonymous>:3:1331)
    at <anonymous>:3:4637
    at Object.dispatch (redux.mjs:172:22)
    at Object.s [as dispatch] (<anonymous>:3:5093)
    at dispatch (redux-toolkit.modern.mjs:598:22)
    at eval (redux-logger.js:1:7667)
    at eval (create-middleware.js:17:22)
    at eval (rtk-query.modern.mjs:2217:17)
    at eval (redux-toolkit.modern.mjs:464:22)
    at eval (redux-thunk.mjs:12:12)
    at eval (redux-toolkit.modern.mjs:368:34)
    at eval (redux-toolkit.modern.mjs:175:12)
    at eval (redux-toolkit.modern.mjs:2151:16)
    at Object.dispatch (redux.mjs:383:38)
    at Object.effect (update-rental-info.listener.ts:44:21)
    at async notifyListener (redux-toolkit.modern.mjs:2082:7) {raisedBy: 'effect'}
JacobShafer commented 5 months ago

It looks like there is another place that is missing the getCurrent method for getting the state id, as described in https://github.com/reduxjs/redux-toolkit/pull/4412

In my case, this happens on a sorted state and only occurs after a seconds add mutation.

PR description:

I had added a getCurrent() util that checks if the value is draftable before calling current(value), but missed a spot. Turns out that a sequence of removeAll() + upsertMany() hits the case where now state.ids is a plain array, and thus current(state.ids) will throw because it's a plain value and not a draft.

This is the relavant line: https://github.com/reduxjs/redux-toolkit/blob/ff65194d84ea80f5293ae4af1a413878cef3eb31/packages/toolkit/src/entities/sorted_state_adapter.ts#L74

markerikson commented 5 months ago

sigh Thanks. Busy atm, but could you throw up a PR to fix that one as well?

JacobShafer commented 5 months ago

Here is a PR to fix this issue.

EskiMojo14 commented 4 months ago

Fix released in v2.2.6 😄