How can I solve this error with Immer - "Uncaught (in promise) TypeError: Cannot perform 'get' on a proxy that has been revoked"

Viewed 548

I' like to push the array is from server in empty array in initialState. As I know to use immer for saving array,

  draft.arr.push({a:1, b:2}) 

But, I don't know why I got the message

Uncaught (in promise) TypeError: Cannot perform 'get' on a proxy that has been revoked

I've tried to use concat and push. But I was not able to get what I want.

const initialState : WorkerState = {
  workersList : []
}

const workers = handleActions<WorkerState, any>(
  {
    [GET_WORKERS_LIST]: (state, action: GetWorkersList) => {
      return produce(state, draft => {
        action.payload.then((res: WorkerInfo[]) => {
           res.map(data => {
            return draft.workerList.push({
              id: data.id,
              name: data.name,
              email: data.email,
              user_type: data.user_type,
              address: data.address,
              salary: data.salary,
              profile_image: data.profile_image,
              birth: data.birth,
              join_date: data.join_date,
              leave_date: data.leave_date,
              working_year: data.working_year,
              grade: data.grade,
              half_vacation: data.half_vacation,
              total_year_vacation: data.total_year_vacation,
              year_vacation: data.year_vacation,
            });
          });
        });
      });
    },initialState,
);
1 Answers

I presume that you use handleAction(s) function of redux-actions package.

It will create multiple redux reducers. Reducers are just pure functions that take the previous state and an action, and return the next state.

You shouldn't include side-effect operations in them, like promise. You should dispatch an action with the data from the API as its the payload. Then you can mutate the immer draft state directly, just replace the workersList directly instead of map + push the item one by one.

E.g.

import produce from 'immer';
import { combineReducers, createStore } from 'redux';
import { createActions, handleActions } from 'redux-actions';

const api = {
  async getWorkersList() {
    return [
      { id: 1, name: 'a' },
      { id: 2, name: 'b' },
    ];
  },
};
const GET_WORKERS_LIST = 'GET_WORKERS_LIST';

interface WorkerState {
  workersList: any[];
}
interface GetWorkersList {
  payload: any[];
}
interface WorkerInfo {}

const initialState: WorkerState = {
  workersList: [],
};

const workers = handleActions<WorkerState, any>(
  {
    [GET_WORKERS_LIST]: (state, action: GetWorkersList) => {
      return produce(state, (draft) => {
        draft.workersList = action.payload;
      });
    },
  },
  initialState,
);

const { getWorkersList } = createActions({
  GET_WORKERS_LIST: (payload) => payload,
});

const rootReducer = combineReducers({ workers });
const store = createStore(rootReducer);
store.subscribe(() => {
  console.log(store.getState().workers);
});

api.getWorkersList().then((res) => {
  store.dispatch(getWorkersList(res));
});

Output:

{ workersList: [ { id: 1, name: 'a' }, { id: 2, name: 'b' } ] }
Related